@jaak.ai/stamps 2.0.0-dev.41 → 2.0.0-dev.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
- package/dist/cjs/jaak-stamps.cjs.entry.js +14 -652
- package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
- package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/collection/components/my-component/my-component.css +40 -0
- package/dist/collection/components/my-component/my-component.js +35 -343
- package/dist/collection/components/my-component/my-component.js.map +1 -1
- package/dist/collection/services/DetectionService.js +1 -164
- package/dist/collection/services/DetectionService.js.map +1 -1
- package/dist/collection/services/ServiceContainer.js +1 -6
- package/dist/collection/services/ServiceContainer.js.map +1 -1
- package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
- package/dist/collection/types/component-types.js +2 -0
- package/dist/collection/types/component-types.js.map +1 -0
- package/dist/components/jaak-stamps.js +15 -663
- package/dist/components/jaak-stamps.js.map +1 -1
- package/dist/esm/jaak-stamps-webcomponent.js +1 -1
- package/dist/esm/jaak-stamps.entry.js +14 -652
- package/dist/esm/jaak-stamps.entry.js.map +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
- package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
- package/dist/jaak-stamps-webcomponent/p-3074405d.entry.js +2 -0
- package/dist/jaak-stamps-webcomponent/p-3074405d.entry.js.map +1 -0
- package/dist/types/components/my-component/my-component.d.ts +4 -45
- package/dist/types/components.d.ts +11 -62
- package/dist/types/services/DetectionService.d.ts +2 -22
- package/dist/types/services/ServiceContainer.d.ts +0 -6
- package/dist/types/services/interfaces/IDetectionService.d.ts +0 -13
- package/dist/types/types/component-types.d.ts +36 -0
- package/package.json +1 -1
- package/dist/collection/services/ImageQualityService.js +0 -329
- package/dist/collection/services/ImageQualityService.js.map +0 -1
- package/dist/collection/services/interfaces/IImageQualityService.js +0 -2
- package/dist/collection/services/interfaces/IImageQualityService.js.map +0 -1
- package/dist/jaak-stamps-webcomponent/p-47f37982.entry.js +0 -2
- package/dist/jaak-stamps-webcomponent/p-47f37982.entry.js.map +0 -1
- package/dist/types/services/ImageQualityService.d.ts +0 -31
- package/dist/types/services/interfaces/IImageQualityService.d.ts +0 -58
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"IImageQualityService.js","sourceRoot":"","sources":["../../../src/services/interfaces/IImageQualityService.ts"],"names":[],"mappings":"","sourcesContent":["export interface BlurMetrics {\n blurScore: number;\n isAcceptable: boolean;\n threshold: number;\n}\n\nexport interface ReflectionMetrics {\n reflectionScore: number;\n hasReflection: boolean;\n threshold: number;\n reflectionAreas: { x: number; y: number; width: number; height: number }[];\n}\n\nexport interface FocusMetrics {\n focusScore: number;\n isFocused: boolean;\n threshold: number;\n edgeStrength: number;\n}\n\nexport interface BrightnessMetrics {\n brightness: number;\n isAcceptable: boolean;\n minThreshold: number;\n maxThreshold: number;\n}\n\nexport interface ContrastMetrics {\n contrast: number;\n isAcceptable: boolean;\n threshold: number;\n}\n\nexport interface ImageQualityResult {\n blur: BlurMetrics;\n reflection: ReflectionMetrics;\n focus: FocusMetrics;\n brightness: BrightnessMetrics;\n contrast: ContrastMetrics;\n overallQuality: 'excellent' | 'good' | 'acceptable' | 'poor';\n qualityScore: number; // 0-100\n issues: string[];\n recommendations: string[];\n}\n\nexport interface IImageQualityService {\n analyzeImageQuality(canvas: HTMLCanvasElement, documentBounds?: { x: number; y: number; w: number; h: number }): ImageQualityResult;\n detectBlur(imageData: ImageData): BlurMetrics;\n detectReflections(imageData: ImageData): ReflectionMetrics;\n measureFocus(imageData: ImageData): FocusMetrics;\n measureBrightness(imageData: ImageData): BrightnessMetrics;\n measureContrast(imageData: ImageData): ContrastMetrics;\n getQualityRecommendations(result: ImageQualityResult): string[];\n}"]}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e,c as t,a as i,h as s}from"./p-BP1Q4KOg.js";class a{debugMode;constructor(e=false){this.debugMode=e}setDebugMode(e){this.debugMode=e}info(...e){if(this.debugMode){console.log(`[JAAK-STAMPS] [INFO] [${(new Date).toLocaleTimeString()}]`,...e)}}warn(...e){if(this.debugMode){console.warn(`[JAAK-STAMPS] [WARN] [${(new Date).toLocaleTimeString()}]`,...e)}}error(...e){if(this.debugMode){console.error(`[JAAK-STAMPS] [ERROR] [${(new Date).toLocaleTimeString()}]`,...e)}}debug(...e){if(this.debugMode){console.debug(`[JAAK-STAMPS] [DEBUG] [${(new Date).toLocaleTimeString()}]`,...e)}}state(e,t){if(this.debugMode){console.log(`[JAAK-STAMPS] [STATE] [${(new Date).toLocaleTimeString()}] ${e}`,t||"")}}performance(e,t){if(this.debugMode){console.log(`[JAAK-STAMPS] [PERF] [${(new Date).toLocaleTimeString()}] ${e}: ${t}ms`)}}}class o{events=new Map;on(e,t){if(!this.events.has(e)){this.events.set(e,[])}this.events.get(e).push(t)}off(e,t){const i=this.events.get(e);if(i){const e=i.indexOf(t);if(e>-1){i.splice(e,1)}}}emit(e,t){const i=this.events.get(e);if(i){i.forEach((i=>{try{i(t)}catch(t){console.error(`Error in event callback for ${e}:`,t)}}))}}once(e,t){const i=s=>{t(s);this.off(e,i)};this.on(e,i)}clear(){this.events.clear()}}class r{eventBus;captureState={step:"front",isCapturing:false,isDetectionPaused:false,isVideoActive:false,isLoading:false,showFlipAnimation:false,showSuccessAnimation:false,bestScore:0,hasScreenshotTaken:false};capturedImages={front:{fullFrame:null,cropped:null},back:{fullFrame:null,cropped:null},metadata:{totalImages:0,processCompleted:false,backCaptureSkipped:false}};constructor(e){this.eventBus=e}getCaptureState(){return{...this.captureState}}updateCaptureState(e){const t={...this.captureState};this.captureState={...this.captureState,...e};this.eventBus.emit("state-changed",{previous:t,current:this.captureState,changes:e})}getCapturedImages(){return JSON.parse(JSON.stringify(this.capturedImages))}setCapturedImages(e){this.capturedImages={...this.capturedImages,...e,metadata:{...this.capturedImages.metadata,...e.metadata}};let t=0;if(this.capturedImages.front.fullFrame&&this.capturedImages.front.cropped){t+=2}if(this.capturedImages.back.fullFrame&&this.capturedImages.back.cropped){t+=2}this.capturedImages.metadata.totalImages=t}reset(){this.captureState={step:"front",isCapturing:false,isDetectionPaused:false,isVideoActive:false,isLoading:false,showFlipAnimation:false,showSuccessAnimation:false,bestScore:0,hasScreenshotTaken:false};this.capturedImages={front:{fullFrame:null,cropped:null},back:{fullFrame:null,cropped:null},metadata:{totalImages:0,processCompleted:false,backCaptureSkipped:false}};this.eventBus.emit("state-changed",{previous:null,current:this.captureState,changes:{reset:true}})}isProcessCompleted(){return this.captureState.step==="completed"}canProceedToBack(){return this.captureState.step==="front"&&this.capturedImages.front.fullFrame!==null&&this.capturedImages.front.cropped!==null}}class n{logger;eventBus;availableCameras=[];selectedCameraId=null;deviceType="desktop";preferredCameraFacing=null;preferredCamera="auto";constructor(e,t,i="auto"){this.logger=e;this.eventBus=t;this.preferredCamera=i}async detectDeviceType(){const e=navigator.userAgent;const t=/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(e);const i=/iPad|Android/i.test(e)&&window.innerWidth>=768;if(i){this.deviceType="tablet"}else if(t){this.deviceType="mobile"}else{this.deviceType="desktop"}this.logger.state("DISPOSITIVO_DETECTADO",{deviceType:this.deviceType,userAgent:navigator.userAgent,screenDimensions:{width:window.innerWidth,height:window.innerHeight}});return this.deviceType}async enumerateDevices(){try{const e=await this.checkCameraPermission();if(e==="denied"){this.logger.error("Permiso de cámara denegado por el usuario");return[]}if(e==="prompt"){const e=await navigator.mediaDevices.getUserMedia({video:true});e.getTracks().forEach((e=>e.stop()))}const t=await navigator.mediaDevices.enumerateDevices();this.availableCameras=t.filter((e=>e.kind==="videoinput"));this.logger.state("CAMARAS_DETECTADAS",{count:this.availableCameras.length,cameras:this.availableCameras.map((e=>({id:e.deviceId,label:e.label||"Unknown Camera"})))});this.setInitialCameraPreference();this.eventBus.emit("camera-changed",this.selectedCameraId);return this.availableCameras}catch(e){this.logger.error("Error al enumerar cámaras disponibles:",e);this.handleCameraPermissionError(e);return[]}}getAvailableCameras(){return[...this.availableCameras]}isMultipleCamerasAvailable(){return this.availableCameras.length>1}getSelectedCameraId(){return this.selectedCameraId}async setSelectedCamera(e){const t=this.availableCameras.find((t=>t.deviceId===e));if(!t){throw new Error(`Camera with ID ${e} not found`)}this.selectedCameraId=e;this.updatePreferredFacing(t);this.savePreference();this.eventBus.emit("camera-changed",e)}getPreferredFacing(){return this.preferredCameraFacing}async setupCamera(e){const t=e||await this.getMaxResolution();const i=await navigator.mediaDevices.getUserMedia({video:t,audio:false});return i}async switchCamera(e){const t=this.availableCameras.find((t=>t.deviceId===e));if(!t){this.logger.warn("Cámara seleccionada no encontrada, re-enumerando dispositivos...");await this.enumerateDevices();return}await this.setSelectedCamera(e);this.logger.state("CAMARA_CAMBIADA",{label:t.label,deviceId:t.deviceId})}async flipToNextCamera(){if(!this.isMultipleCamerasAvailable())return;const e=this.availableCameras.findIndex((e=>e.deviceId===this.selectedCameraId));const t=(e+1)%this.availableCameras.length;const i=this.availableCameras[t];await this.switchCamera(i.deviceId)}savePreference(){try{const e={cameraId:this.selectedCameraId,facing:this.preferredCameraFacing,timestamp:Date.now()};localStorage.setItem("jaak-stamps-camera-preference",JSON.stringify(e));this.logger.state("PREFERENCIA_CAMARA_GUARDADA",e)}catch(e){this.logger.warn("Error al guardar preferencia de cámara:",e)}}loadPreference(){try{const e=localStorage.getItem("jaak-stamps-camera-preference");if(e){const t=JSON.parse(e);const i=this.availableCameras.some((e=>e.deviceId===t.cameraId));if(i){this.selectedCameraId=t.cameraId;this.preferredCameraFacing=t.facing;this.logger.state("PREFERENCIA_CAMARA_CARGADA",t)}}}catch(e){this.logger.warn("Error al cargar preferencia de cámara:",e)}}isRearCamera(e){const t=e.getVideoTracks()[0];if(!t)return false;const i=t.getSettings();return i.facingMode==="environment"}getCameraInfo(){return{availableCameras:this.availableCameras.map((e=>({id:e.deviceId,label:e.label||"Unknown Camera",selected:e.deviceId===this.selectedCameraId}))),selectedCameraId:this.selectedCameraId,deviceType:this.deviceType,isMultipleCamerasAvailable:this.isMultipleCamerasAvailable(),preferredFacing:this.preferredCameraFacing}}async checkCameraPermission(){try{if(!navigator.permissions){return"prompt"}const e=await navigator.permissions.query({name:"camera"});return e.state}catch(e){this.logger.warn("No se pudo verificar permisos de cámara:",e);return"prompt"}}handleCameraPermissionError(e){this.availableCameras=[];this.eventBus.emit("error",new Error(`Camera permission error: ${e.message}`))}setInitialCameraPreference(){if(this.availableCameras.length===0)return;if(this.preferredCamera==="front"){this.selectFrontCamera()}else if(this.preferredCamera==="back"){this.selectBackCamera()}else{this.selectAutoCamera()}}selectFrontCamera(){this.preferredCameraFacing="user";const e=this.availableCameras.find((e=>e.label.toLowerCase().includes("front")||e.label.toLowerCase().includes("user")||e.label.toLowerCase().includes("selfie")||!e.label.toLowerCase().includes("back")&&!e.label.toLowerCase().includes("rear")));this.selectedCameraId=e?e.deviceId:this.availableCameras[0].deviceId;this.logger.state("CAMARA_FRONTAL_SELECCIONADA",{label:e?.label||this.availableCameras[0].label,deviceId:this.selectedCameraId})}selectBackCamera(){this.preferredCameraFacing="environment";const e=this.availableCameras.find((e=>e.label.toLowerCase().includes("back")||e.label.toLowerCase().includes("rear")||e.label.toLowerCase().includes("environment")));this.selectedCameraId=e?e.deviceId:this.availableCameras[0].deviceId;this.logger.state("CAMARA_TRASERA_SELECCIONADA",{label:e?.label||this.availableCameras[0].label,deviceId:this.selectedCameraId})}selectAutoCamera(){if(this.deviceType==="mobile"||this.deviceType==="tablet"){this.selectBackCamera();this.logger.state("CAMARA_AUTO_SELECCIONADA_MOBILE",{type:"rear"})}else{this.selectedCameraId=this.availableCameras[0].deviceId;this.logger.state("CAMARA_AUTO_SELECCIONADA_DESKTOP",{label:this.availableCameras[0].label,deviceId:this.selectedCameraId})}}updatePreferredFacing(e){const t=e.label.toLowerCase().includes("back")||e.label.toLowerCase().includes("rear")||e.label.toLowerCase().includes("environment");this.preferredCameraFacing=t?"environment":"user"}async getMaxResolution(){try{const e={};if(this.selectedCameraId){e.deviceId={exact:this.selectedCameraId}}else if(this.preferredCameraFacing){e.facingMode=this.preferredCameraFacing}else{e.facingMode="environment"}const t=await navigator.mediaDevices.getUserMedia({video:e});const i=t.getVideoTracks()[0];const s=i.getCapabilities();t.getTracks().forEach((e=>e.stop()));const a={...e};this.applyAdvancedCameraSettings(a,s);if(s.width&&s.height){const e=Math.min(s.width.max,1920);const t=Math.min(s.height.max,1080);const i=/iPad|Android/i.test(navigator.userAgent)&&window.innerWidth>=768;if(i){a.width={ideal:Math.min(e,1280)};a.height={ideal:Math.min(t,720)}}else{a.width={ideal:e};a.height={ideal:t}}}this.logger.state("CONFIGURACION_CAMARA_OPTIMIZADA",{constraints:a,capabilities:this.getCapabilitiesSummary(s)});return a}catch(e){this.logger.warn("No se pudieron obtener capacidades de cámara, usando configuración de respaldo");const t=/iPad|Android/i.test(navigator.userAgent)&&window.innerWidth>=768;const i={width:{ideal:t?1280:1920},height:{ideal:t?720:1080}};this.applyBasicFocusSettings(i);if(this.selectedCameraId){i.deviceId={exact:this.selectedCameraId}}else if(this.preferredCameraFacing){i.facingMode=this.preferredCameraFacing}else{i.facingMode="environment"}return i}}applyAdvancedCameraSettings(e,t){if(t.frameRate){e.frameRate={ideal:30,min:15,max:60}}if(t.width&&t.height){e.width={ideal:Math.min(1920,t.width.max||1920),min:640};e.height={ideal:Math.min(1080,t.height.max||1080),min:480}}const i=[];const s={};if(t.focusMode){if(t.focusMode.includes("continuous")){s.focusMode="continuous"}else if(t.focusMode.includes("single-shot")){s.focusMode="single-shot"}}if(t.focusDistance){s.focusDistance={ideal:.4,min:.2,max:1}}if(t.zoom){s.zoom={ideal:1,min:t.zoom.min,max:Math.min(t.zoom.max,3)}}if(Object.keys(s).length>0){i.push(s)}if(i.length>0){e.advanced=i}}applyBasicFocusSettings(e){const t={focusMode:"continuous",exposureMode:"continuous",whiteBalanceMode:"continuous"};if(!e.advanced){e.advanced=[]}e.advanced.push(t);e.frameRate={ideal:30}}getCapabilitiesSummary(e){return{hasAutoFocus:!!e.focusMode,hasFocusDistance:!!e.focusDistance,hasExposureControl:!!e.exposureMode,hasWhiteBalance:!!e.whiteBalanceMode,hasZoom:!!e.zoom,hasTorch:e.torch!==undefined,hasImageControls:!!(e.brightness||e.contrast||e.saturation||e.sharpness),resolutionRange:e.width&&e.height?`${e.width.min}x${e.height.min} - ${e.width.max}x${e.height.max}`:"unknown"}}async setTorchEnabled(e,t){try{if(!t){this.logger.warn("No hay stream disponible para controlar el flash");return false}const i=t.getVideoTracks()[0];if(!i){this.logger.warn("No hay track de video disponible");return false}const s=i.getCapabilities();if(s.torch===undefined){this.logger.warn("El dispositivo no soporta control de flash");return false}await i.applyConstraints({advanced:[{torch:e}]});this.logger.state("FLASH_CONTROLADO",{enabled:e});return true}catch(e){this.logger.error("Error al controlar el flash:",e);return false}}async focusAtPoint(e,t,i){try{if(!i){this.logger.warn("No hay stream disponible para enfocar");return false}const s=i.getVideoTracks()[0];if(!s){this.logger.warn("No hay track de video disponible");return false}const a=s.getCapabilities();if(!a.focusMode||!a.focusMode.includes("single-shot")){this.logger.warn("El dispositivo no soporta enfoque manual");return false}await s.applyConstraints({advanced:[{focusMode:"single-shot"}]});setTimeout((async()=>{try{await s.applyConstraints({advanced:[{focusMode:"continuous"}]})}catch(e){this.logger.warn("Error al volver a enfoque continuo:",e)}}),1e3);this.logger.state("ENFOQUE_MANUAL_ACTIVADO",{x:e,y:t});return true}catch(e){this.logger.error("Error al enfocar manualmente:",e);return false}}}class c{getDeviceInfo(){const e=navigator;const t=e.deviceMemory||e.hardwareConcurrency||4;const i=e.connection||e.mozConnection||e.webkitConnection;const s=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:t,isLowMemory:true,isSlowConnection:s}}getSessionOptions(e){return{executionProviders:["wasm"],graphOptimizationLevel:"basic",logSeverityLevel:4,logVerbosityLevel:0,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1}}shouldUseSequentialLoading(){return true}}class l{getDeviceInfo(){const e=navigator;const t=e.deviceMemory||e.hardwareConcurrency||4;const i=e.connection||e.mozConnection||e.webkitConnection;const s=i&&(i.effectiveType==="slow-2g"||i.effectiveType==="2g");return{estimatedRAM:t,isLowMemory:false,isSlowConnection:s}}getSessionOptions(e){return{executionProviders:["webgl","wasm"],graphOptimizationLevel:"all",logSeverityLevel:e?2:4,logVerbosityLevel:0,enableCpuMemArena:true,enableMemPattern:true,executionMode:"parallel",interOpNumThreads:2,intraOpNumThreads:2}}shouldUseSequentialLoading(){return false}}class d{static createStrategy(){const e=navigator;const t=e.deviceMemory||e.hardwareConcurrency||4;const i=t<=4;if(i){return new c}else{return new l}}}class h{logger;BLUR_THRESHOLD=80;FOCUS_THRESHOLD=40;REFLECTION_THRESHOLD=240;MIN_BRIGHTNESS=50;MAX_BRIGHTNESS=200;MIN_CONTRAST=30;constructor(e){this.logger=e}analyzeImageQuality(e,t){const i=e.getContext("2d");if(!i){throw new Error("Unable to get canvas context")}let s;if(t){s=i.getImageData(t.x,t.y,t.w,t.h)}else{s=i.getImageData(0,0,e.width,e.height)}const a=this.detectBlur(s);const o=this.detectReflections(s);const r=this.measureFocus(s);const n=this.measureBrightness(s);const c=this.measureContrast(s);const l=this.calculateOverallQuality(a,o,r,n,c);const d=this.getQualityLevel(l);const h=this.identifyIssues(a,o,r,n,c);const f=this.getQualityRecommendations({blur:a,reflection:o,focus:r,brightness:n,contrast:c,overallQuality:d,qualityScore:l,issues:h,recommendations:[]});const p={blur:a,reflection:o,focus:r,brightness:n,contrast:c,overallQuality:d,qualityScore:l,issues:h,recommendations:f};this.logger.state("CALIDAD_IMAGEN_ANALIZADA",{qualityScore:l,overallQuality:d,issues:h.length,hasBlur:!a.isAcceptable,hasReflection:o.hasReflection,isFocused:r.isFocused});return p}detectBlur(e){const{data:t,width:i,height:s}=e;let a=0;let o=0;for(let e=1;e<s-1;e++){for(let s=1;s<i-1;s++){const r=(e*i+s)*4;const n=.299*t[r]+.587*t[r+1]+.114*t[r+2];const c=[this.getGrayscale(t,s-1,e-1,i),this.getGrayscale(t,s,e-1,i),this.getGrayscale(t,s+1,e-1,i),this.getGrayscale(t,s-1,e,i),this.getGrayscale(t,s+1,e,i),this.getGrayscale(t,s-1,e+1,i),this.getGrayscale(t,s,e+1,i),this.getGrayscale(t,s+1,e+1,i)];const l=8*n-c.reduce(((e,t)=>e+t),0);a+=l*l;o++}}const r=Math.sqrt(a/o);const n=r>this.BLUR_THRESHOLD;return{blurScore:r,isAcceptable:n,threshold:this.BLUR_THRESHOLD}}detectReflections(e){const{data:t,width:i,height:s}=e;let a=0;const o=i*s;const r=[];const n=Array(s).fill(null).map((()=>Array(i).fill(false)));for(let e=0;e<s;e++){for(let s=0;s<i;s++){const o=(e*i+s)*4;const r=(t[o]+t[o+1]+t[o+2])/3;if(r>this.REFLECTION_THRESHOLD){n[e][s]=true;a++}}}const c=Array(s).fill(null).map((()=>Array(i).fill(false)));for(let e=0;e<s;e++){for(let t=0;t<i;t++){if(n[e][t]&&!c[e][t]){const a=this.findConnectedRegion(n,c,t,e,i,s);if(a.size>100){r.push({x:a.minX,y:a.minY,width:a.maxX-a.minX,height:a.maxY-a.minY})}}}}const l=a/o*100;const d=l>5||r.length>0;return{reflectionScore:l,hasReflection:d,threshold:5,reflectionAreas:r}}measureFocus(e){const{data:t,width:i,height:s}=e;let a=0;let o=0;for(let e=1;e<s-1;e++){for(let s=1;s<i-1;s++){const r=this.sobelX(t,s,e,i);const n=this.sobelY(t,s,e,i);const c=Math.sqrt(r*r+n*n);a+=c;o++}}const r=o>0?a/o:0;const n=r>this.FOCUS_THRESHOLD;return{focusScore:r,isFocused:n,threshold:this.FOCUS_THRESHOLD,edgeStrength:a}}measureBrightness(e){const{data:t}=e;let i=0;const s=t.length/4;for(let e=0;e<t.length;e+=4){const s=(t[e]+t[e+1]+t[e+2])/3;i+=s}const a=i/s;const o=a>=this.MIN_BRIGHTNESS&&a<=this.MAX_BRIGHTNESS;return{brightness:a,isAcceptable:o,minThreshold:this.MIN_BRIGHTNESS,maxThreshold:this.MAX_BRIGHTNESS}}measureContrast(e){const{data:t}=e;let i=255;let s=0;for(let e=0;e<t.length;e+=4){const a=(t[e]+t[e+1]+t[e+2])/3;i=Math.min(i,a);s=Math.max(s,a)}const a=s-i;const o=a>this.MIN_CONTRAST;return{contrast:a,isAcceptable:o,threshold:this.MIN_CONTRAST}}getQualityRecommendations(e){const t=[];if(!e.blur.isAcceptable){t.push("Mantenga el dispositivo estable para reducir el desenfoque");t.push("Acérquese al documento para mejorar la nitidez")}if(e.reflection.hasReflection){t.push("Cambie el ángulo del dispositivo para evitar reflejos");t.push("Mejore la iluminación indirecta del área")}if(!e.focus.isFocused){t.push("Permita que la cámara enfoque automáticamente");t.push("Toque la pantalla sobre el documento para enfocar")}if(!e.brightness.isAcceptable){if(e.brightness.brightness<e.brightness.minThreshold){t.push("Aumente la iluminación del área");t.push("Muévase a un lugar con mejor luz")}else{t.push("Reduzca la iluminación directa sobre el documento");t.push("Evite la luz solar directa")}}if(!e.contrast.isAcceptable){t.push("Mejore la iluminación para aumentar el contraste");t.push("Asegúrese de que el fondo contraste con el documento")}if(t.length===0){t.push("La calidad de la imagen es óptima para la captura")}return t}calculateOverallQuality(e,t,i,s,a){let o=0;o+=e.isAcceptable?25:Math.max(0,e.blurScore/this.BLUR_THRESHOLD*25);o+=t.hasReflection?Math.max(0,20-t.reflectionScore*2):20;o+=i.isFocused?25:Math.max(0,i.focusScore/this.FOCUS_THRESHOLD*25);if(s.isAcceptable){o+=15}else{const e=Math.abs(s.brightness-(s.minThreshold+s.maxThreshold)/2);o+=Math.max(0,15-e/10)}o+=a.isAcceptable?15:Math.max(0,a.contrast/this.MIN_CONTRAST*15);return Math.round(Math.max(0,Math.min(100,o)))}getQualityLevel(e){if(e>=85)return"excellent";if(e>=70)return"good";if(e>=50)return"acceptable";return"poor"}identifyIssues(e,t,i,s,a){const o=[];if(!e.isAcceptable){o.push("Imagen desenfocada por movimiento")}if(t.hasReflection){o.push("Reflejos detectados en el documento")}if(!i.isFocused){o.push("Documento fuera de foco")}if(!s.isAcceptable){if(s.brightness<s.minThreshold){o.push("Iluminación insuficiente")}else{o.push("Imagen sobreexpuesta")}}if(!a.isAcceptable){o.push("Contraste insuficiente")}return o}getGrayscale(e,t,i,s){const a=(i*s+t)*4;return.299*e[a]+.587*e[a+1]+.114*e[a+2]}findConnectedRegion(e,t,i,s,a,o){const r=[{x:i,y:s}];let n=0;let c=i,l=i,d=s,h=s;while(r.length>0){const{x:i,y:s}=r.pop();if(i<0||i>=a||s<0||s>=o||t[s][i]||!e[s][i]){continue}t[s][i]=true;n++;c=Math.min(c,i);l=Math.max(l,i);d=Math.min(d,s);h=Math.max(h,s);r.push({x:i+1,y:s},{x:i-1,y:s},{x:i,y:s+1},{x:i,y:s-1})}return{size:n,minX:c,maxX:l,minY:d,maxY:h}}sobelX(e,t,i,s){const a=[[-1,0,1],[-2,0,2],[-1,0,1]];let o=0;for(let r=-1;r<=1;r++){for(let n=-1;n<=1;n++){const c=this.getGrayscale(e,t+n,i+r,s);o+=c*a[r+1][n+1]}}return o}sobelY(e,t,i,s){const a=[[-1,-2,-1],[0,0,0],[1,2,1]];let o=0;for(let r=-1;r<=1;r++){for(let n=-1;n<=1;n++){const c=this.getGrayscale(e,t+n,i+r,s);o+=c*a[r+1][n+1]}}return o}}class f{logger;debug;useDocumentClassification;qualityThresholds;session;mobileNetSession;mobileNetClassMap;modelLoaded=false;deviceStrategy;imageQualityService;MODEL_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/ddmyp-v2.onnx";MOBILENET_MODEL_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/cdmmp-v1.onnx";MOBILENET_CLASSES_PATH="https://storage.googleapis.com/jaak-static/web/component/stamps/cdmmp-v1.json";INPUT_SIZE=320;CONFIDENCE_THRESHOLD=.6;preprocessCanvas;preprocessCtx;captureCanvas;constructor(e,t=false,i=false,s={}){this.logger=e;this.debug=t;this.useDocumentClassification=i;this.qualityThresholds=s;this.deviceStrategy=d.createStrategy();this.imageQualityService=new h(e);this.initializeCanvasPool()}async loadModel(){if(this.modelLoaded||this.session){this.logger.state("MODELO_YA_PRECARGADO",{sessionExists:!!this.session,modelPreloaded:this.modelLoaded});return}try{this.logger.state("PRECARGANDO_MODELO_DETECCION",{modelPath:this.MODEL_PATH});const e=this.deviceStrategy.getSessionOptions(this.debug);try{this.session=await window.ort.InferenceSession.create(this.MODEL_PATH,e)}catch(e){if(e.message.includes("failed to allocate a buffer")){this.logger.warn("Fallo en asignación de buffer durante precarga, intentando con configuración mínima");const e={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1};this.session=await window.ort.InferenceSession.create(this.MODEL_PATH,e)}else{throw e}}this.modelLoaded=true;this.logger.state("MODELO_DETECCION_CARGADO_EXITOSAMENTE",{sessionCreated:!!this.session})}catch(e){this.logger.error("Error al precargar modelo de detección:",e);throw e}}async loadClassificationModel(){if(!this.useDocumentClassification){return}try{this.logger.state("CARGANDO_MODELO_MOBILENET",{path:this.MOBILENET_MODEL_PATH});const e=await fetch(this.MOBILENET_CLASSES_PATH);if(!e.ok){throw new Error(`Failed to load class map: ${this.MOBILENET_CLASSES_PATH}`)}this.mobileNetClassMap=await e.json();this.logger.state("CLASES_MOBILENET_CARGADAS",{classCount:Object.keys(this.mobileNetClassMap).length});const t=this.deviceStrategy.getSessionOptions(this.debug);try{this.mobileNetSession=await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH,t)}catch(e){if(e.message.includes("failed to allocate a buffer")){this.logger.warn("Fallo en asignación de buffer de MobileNet, intentando con configuración mínima");const e={executionProviders:["wasm"],graphOptimizationLevel:"disabled",logSeverityLevel:4,enableCpuMemArena:false,enableMemPattern:false,executionMode:"sequential",interOpNumThreads:1,intraOpNumThreads:1};this.mobileNetSession=await window.ort.InferenceSession.create(this.MOBILENET_MODEL_PATH,e)}else{throw e}}this.logger.state("MODELO_MOBILENET_CARGADO_EXITOSAMENTE",{sessionCreated:!!this.mobileNetSession})}catch(e){this.logger.error("Error al cargar modelo MobileNet:",e);throw e}}isModelLoaded(){return this.modelLoaded&&!!this.session}preprocess(e){if(!this.preprocessCanvas||!this.preprocessCtx){this.initializeCanvasPool()}this.preprocessCtx.clearRect(0,0,this.INPUT_SIZE,this.INPUT_SIZE);this.preprocessCtx.drawImage(e,0,0,this.INPUT_SIZE,this.INPUT_SIZE);const t=this.preprocessCtx.getImageData(0,0,this.INPUT_SIZE,this.INPUT_SIZE);const[i,s,a]=[[],[],[]];const{data:o}=t;for(let e=0;e<o.length;e+=4){i.push(o[e]/255);s.push(o[e+1]/255);a.push(o[e+2]/255)}const r=new Float32Array(i.concat(s,a));const n=new Uint16Array(r.length);for(let e=0;e<r.length;e++){n[e]=this.float32ToFloat16(r[e])}return new window.ort.Tensor("float16",n,[1,3,this.INPUT_SIZE,this.INPUT_SIZE])}async runInference(e){if(!this.session){throw new Error("Detection model not loaded")}const t={[this.session.inputNames[0]]:e};const i=await this.session.run(t);const s=i[this.session.outputNames[0]].data;const a=[];for(let e=0;e<s.length;e+=6){const[t,i,o,r,n,c]=s.slice(e,e+6);if(n>this.CONFIDENCE_THRESHOLD){a.push({x:t,y:i,w:o-t,h:r-i,score:n,classId:c})}}return a}async classifyDocument(e){if(!this.mobileNetSession||!this.mobileNetClassMap){this.logger.warn("Modelo MobileNet no está cargado, saltando clasificación");return null}try{this.logger.state("CLASIFICANDO_DOCUMENTO",{timestamp:Date.now()});const t=this.preprocessMobileNet(e);const i={input:t};const s=await this.mobileNetSession.run(i);const a=s[Object.keys(s)[0]].data;const o=a.reduce(((e,t,i,s)=>t>s[e]?i:e),0);const r=a[o];const n=this.mobileNetClassMap[o.toString()]||"unknown";this.logger.state("DOCUMENTO_CLASIFICADO",{class:n,confidence:r.toFixed(3),classIndex:o,timestamp:Date.now()});return{class:n,confidence:r,classIndex:o}}catch(e){this.logger.error("Error al clasificar documento:",e);return null}}checkSideAlignment(e,t){const{INPUT_SIZE:i,ID1_ASPECT_RATIO:s,shouldMirrorVideo:a,alignmentTolerance:o,maskSize:r,videoRef:n}=t;if(!n){return{top:false,right:false,bottom:false,left:false}}const c=n.videoWidth;const l=n.videoHeight;if(c===0||l===0){return{top:false,right:false,bottom:false,left:false}}const d=c/l;const h=1;let f,p;if(d>h){f=i;p=i/d}else{p=i;f=i*d}const u=p*s;let m,b;const g=r/100;if(u<=f){b=p*g;m=b*s}else{m=f*g;b=m/s}const x=m*(i/f);const y=b*(i/p);const w=i/2;const v=i/2;const A=w-x/2;const C=w+x/2;const k=v-y/2;const S=v+y/2;let E=e.x;let M=e.x+e.w;const I=e.y;const T=e.y+e.h;if(a){const e=E;const t=M;E=i-t;M=i-e}const D=o;const O=Math.abs(I-k)<=D;const R=Math.abs(M-C)<=D;const _=Math.abs(T-S)<=D;const N=Math.abs(E-A)<=D;return{top:O&&N,right:O&&R,bottom:_&&N,left:_&&R}}isCardInFrame(e){const t=e.x+e.w/2;const i=e.y+e.h/2;const s=this.INPUT_SIZE/2;const a=this.INPUT_SIZE/2;const o=40;const r=30;const n=Math.abs(t-s)<o&&Math.abs(i-a)<r;const c=e.w>150&&e.w<300&&e.h>90&&e.h<200;return n&&c}areAllSidesAligned(e){return e.top&&e.right&&e.bottom&&e.left}cleanup(){this.cleanupCanvasPool();if(this.session){this.session.release?.();this.session=undefined}if(this.mobileNetSession){this.mobileNetSession.release?.();this.mobileNetSession=undefined}this.mobileNetClassMap=undefined;this.modelLoaded=false;this.logger.state("DETECCION_SERVICE_LIMPIADO",{timestamp:Date.now()})}initializeCanvasPool(){this.preprocessCanvas=document.createElement("canvas");this.preprocessCanvas.width=this.INPUT_SIZE;this.preprocessCanvas.height=this.INPUT_SIZE;this.preprocessCtx=this.preprocessCanvas.getContext("2d",{alpha:false,willReadFrequently:true});this.captureCanvas=document.createElement("canvas");this.logger.state("CANVAS_POOL_INICIALIZADO",{preprocessCanvasSize:this.INPUT_SIZE})}cleanupCanvasPool(){if(this.preprocessCanvas){this.preprocessCtx=undefined;this.preprocessCanvas=undefined}if(this.captureCanvas){this.captureCanvas=undefined}}float32ToFloat16(e){const t=new ArrayBuffer(4);const i=new DataView(t);i.setFloat32(0,e,true);const s=i.getUint32(0,true);const a=s>>31&1;const o=s>>23&255;const r=s&8388607;let n=o-127+15;if(o===0){n=0}else if(o===255){n=31}else if(n>=31){n=31;return a<<15|n<<10}else if(n<=0){return a<<15}return a<<15|n<<10|r>>13}preprocessMobileNet(e){const t=document.createElement("canvas");t.width=224;t.height=224;const i=t.getContext("2d");i.drawImage(e,0,0,224,224);const s=i.getImageData(0,0,224,224);const a=s.data;const o=224*224;const r=new Float32Array(3*o);for(let e=0;e<o;e++){r[e]=(a[e*4+0]/255-.5)/.5;r[o+e]=(a[e*4+1]/255-.5)/.5;r[2*o+e]=(a[e*4+2]/255-.5)/.5}return new window.ort.Tensor("float32",r,[1,3,224,224])}validateImageQuality(e,t){const i=document.createElement("canvas");i.width=e.videoWidth;i.height=e.videoHeight;const s=i.getContext("2d");s.drawImage(e,0,0);let a;if(t){const i=e.videoWidth/this.INPUT_SIZE;const s=e.videoHeight/this.INPUT_SIZE;a={x:Math.max(0,t.x*i),y:Math.max(0,t.y*s),w:Math.min(t.w*i,e.videoWidth),h:Math.min(t.h*s,e.videoHeight)}}return this.imageQualityService.analyzeImageQuality(i,a)}isImageQualityAcceptable(e){const t=this.qualityThresholds.minQualityScore??45;const i=this.qualityThresholds.minFocusScore??16;const s=this.qualityThresholds.minBlurScore??22;const a=this.qualityThresholds.maxReflectionScore??15;if(e.qualityScore<t){this.logger.state("QUALITY_REJECTION_SCORE",{qualityScore:e.qualityScore,minQualityScore:t,reason:"score_too_low"});return false}if(e.focus.focusScore<i){this.logger.state("QUALITY_REJECTION_FOCUS",{focusScore:e.focus.focusScore,minFocusScore:i,reason:"severe_focus_issues"});return false}if(e.blur.blurScore<s){this.logger.state("QUALITY_REJECTION_BLUR",{blurScore:e.blur.blurScore,minBlurScore:s,reason:"severe_blur_issues"});return false}if(e.reflection.hasReflection&&e.reflection.reflectionScore>a){this.logger.state("QUALITY_REJECTION_REFLECTION",{hasReflection:e.reflection.hasReflection,reflectionScore:e.reflection.reflectionScore,maxReflectionScore:a,reason:"severe_reflection_issues"});return false}this.logger.state("QUALITY_ACCEPTANCE",{qualityScore:e.qualityScore,focusScore:e.focus.focusScore,blurScore:e.blur.blurScore,reflectionScore:e.reflection.reflectionScore,issues:e.issues,reason:"quality_acceptable"});return true}updateQualityThresholds(e){this.qualityThresholds={...this.qualityThresholds,...e};this.logger.state("QUALITY_THRESHOLDS_UPDATED",{newThresholds:this.qualityThresholds})}getQualityThresholds(){return{...this.qualityThresholds}}getQualityFeedback(e){if(e.qualityScore>=85){return"Calidad excelente - listo para capturar"}else if(e.qualityScore>=70){return"Buena calidad - puede capturar"}else if(e.qualityScore>=50){const t=e.issues[0];return t?`Calidad aceptable - ${t.toLowerCase()}`:"Calidad aceptable"}else{const t=e.issues.slice(0,2).join(", ").toLowerCase();return`Calidad insuficiente - ${t}`}}async runInferenceWithQuality(e,t){const i=await this.runInference(e);const s=i.length>0?i.reduce(((e,t)=>t.score>e.score?t:e)):undefined;const a=this.validateImageQuality(t,s);const o=this.isImageQualityAcceptable(a);const r=this.getQualityFeedback(a);this.logger.state("DETECCION_CON_CALIDAD",{detectionsCount:i.length,qualityScore:a.qualityScore,canCapture:o,issues:a.issues.length,bestDetectionScore:s?.score||0});return{detections:i,qualityResult:a,canCapture:o,feedback:r}}getQuickQualityFeedback(e){const t=document.createElement("canvas");t.width=Math.min(e.videoWidth,640);t.height=Math.min(e.videoHeight,480);const i=t.getContext("2d");i.drawImage(e,0,0,t.width,t.height);const s=i.getImageData(0,0,t.width,t.height);const a=this.imageQualityService.detectBlur(s);const o=this.imageQualityService.detectReflections(s);const r=this.imageQualityService.measureFocus(s);let n="Analizando calidad...";if(!a.isAcceptable){n="Estabilice el dispositivo"}else if(o.hasReflection){n="Evite reflejos en el documento"}else if(!r.isFocused){n="Permitiendo enfoque automático..."}else{n="Calidad óptima"}return{hasBlur:!a.isAcceptable,hasReflections:o.hasReflection,isFocused:r.isFocused,feedback:n}}}class p{services=new Map;constructor(e){this.initializeServices(e)}initializeServices(e){const t=new o;const i=new a(e.debug);const s=new r(t);const c=new n(i,t,e.preferredCamera);const l=new f(i,e.debug,e.useDocumentClassification,{minQualityScore:e.minQualityScore,minFocusScore:e.minFocusScore,minBlurScore:e.minBlurScore,maxReflectionScore:e.maxReflectionScore});this.services.set("eventBus",t);this.services.set("logger",i);this.services.set("stateManager",s);this.services.set("cameraService",c);this.services.set("detectionService",l)}get(e){const t=this.services.get(e);if(!t){throw new Error(`Service ${e} not found`)}return t}getLogger(){return this.get("logger")}getEventBus(){return this.get("eventBus")}getStateManager(){return this.get("stateManager")}getCameraService(){return this.get("cameraService")}getDetectionService(){return this.get("detectionService")}updateConfig(e){if(e.debug!==undefined){const t=this.services.get("logger");t.setDebugMode(e.debug)}}cleanup(){this.getDetectionService().cleanup();this.getEventBus().clear();this.services.clear()}}const u=":host{display:block;width:100%;height:100%;font-family:system-ui, -apple-system, sans-serif;color:#1a1a1a}.detector-container{display:flex;flex-direction:column;align-items:center;width:100%;height:100%}h1{font-size:24px;font-weight:500;color:#333;margin:0 0 24px 0}.video-container{position:relative;width:100%;height:100%;background:#333;border:1px solid #e0e0e0;border-radius:8px;overflow:hidden}video,.detection-overlay{position:absolute;width:100%;height:100%;border-radius:8px}video.mirror,.detection-overlay.mirror{transform:rotateY(180deg)}.detection-overlay{z-index:1;pointer-events:none}video{z-index:0}.detection-box{transition:opacity 0.2s ease}.status{margin-top:16px;font-size:12px;color:#666}.overlay-mask{position:absolute;top:0;left:0;width:100%;height:100%;z-index:10;display:block;pointer-events:none}.card-outline{position:absolute;top:var(--mask-center-y, 50%);left:var(--mask-center-x, 50%);transform:translate(-50%, -50%);width:var(--mask-width, 88%);height:var(--mask-height, 55%);border:none;border-radius:4px;background:transparent;opacity:0.8}.side{position:absolute;background:#999;transition:background-color 0.3s ease;border-radius:1px}.side-top.aligned{border-left-color:#28a745;border-top-color:#28a745}.side-right.aligned{border-right-color:#28a745;border-top-color:#28a745}.side-bottom.aligned{border-left-color:#28a745;border-bottom-color:#28a745}.side-left.aligned{border-right-color:#28a745;border-bottom-color:#28a745}.side-top{top:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-right{top:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-top:6px solid #ffffff;background:transparent}.side-bottom{bottom:-3px;left:-3px;width:30px;height:30px;border-left:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.side-left{bottom:-3px;right:-3px;width:30px;height:30px;border-right:6px solid #ffffff;border-bottom:6px solid #ffffff;background:transparent}.guide-text{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);color:#fff;font-size:14px;font-weight:600;text-align:center;white-space:normal;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;z-index:20}.quality-indicator{position:absolute;top:20px;right:20px;display:flex;align-items:center;gap:8px;background:rgba(0, 0, 0, 0.8);padding:8px 12px;border-radius:20px;z-index:25;transition:all 0.3s ease}.quality-indicator.warning{background:rgba(255, 152, 0, 0.9)}.quality-indicator.good{background:rgba(76, 175, 80, 0.9)}.quality-score{color:#fff;font-size:12px;font-weight:600;min-width:30px;text-align:center}.quality-status{width:20px;height:20px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:bold;color:#fff;transition:all 0.3s ease}.quality-status.ready{background:#4CAF50}.quality-status.not-ready{background:#f44336}.card-outline.quality-warning{animation:qualityWarning 1s ease-in-out infinite alternate}@keyframes qualityWarning{0%{box-shadow:0 0 0 3px rgba(255, 152, 0, 0.6)}100%{box-shadow:0 0 0 6px rgba(255, 152, 0, 0.3)}}.capture-animation{position:absolute;top:0;left:0;width:100%;height:100%;background:#fff;opacity:0;z-index:30;pointer-events:none;animation:captureFlash 0.6s ease-out}@keyframes captureFlash{0%{opacity:0}15%{opacity:0.8}30%{opacity:0}45%{opacity:0.4}60%{opacity:0}100%{opacity:0}}.card-outline.capturing{animation:pulseGreen 0.6s ease-out}@keyframes pulseGreen{0%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}50%{border-color:#28a745;box-shadow:0 0 0 8px rgba(40, 167, 69, 0.6)}100%{border-color:#28a745;box-shadow:0 0 0 4px rgba(40, 167, 69, 0)}}.flip-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showFlipInstruction 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.id-card-icon{width:80px;height:50px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:8px;position:relative;animation:flipCard 2s ease-in-out infinite;box-shadow:0 4px 12px rgba(0, 0, 0, 0.3)}.id-card-icon::before{content:'';position:absolute;top:8px;left:8px;width:16px;height:12px;background:rgba(255, 255, 255, 0.9);border-radius:2px}.id-card-icon::after{content:'';position:absolute;top:25px;left:8px;width:64px;height:3px;background:rgba(255, 255, 255, 0.7);border-radius:1px;box-shadow:0 6px 0 rgba(255, 255, 255, 0.7), 0 12px 0 rgba(255, 255, 255, 0.7)}.flip-text{margin-top:12px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px}@keyframes showFlipInstruction{0%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.8)}}@keyframes flipCard{0%{transform:rotateY(0deg)}50%{transform:rotateY(180deg)}100%{transform:rotateY(360deg)}}.success-animation{position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);z-index:35;pointer-events:none;opacity:0;animation:showSuccessMessage 3s ease-in-out;display:flex;flex-direction:column;align-items:center;justify-content:center}.check-icon{width:80px;height:80px;background:linear-gradient(135deg, #6c757d 0%, #495057 100%);border-radius:50%;position:relative;animation:bounceSuccess 0.6s ease-out;box-shadow:0 4px 16px rgba(108, 117, 125, 0.4);display:flex;align-items:center;justify-content:center}.check-icon::before{content:'';position:absolute;width:20px;height:35px;border:4px solid #fff;border-top:none;border-left:none;transform:rotate(45deg);animation:drawCheck 0.4s ease-out 0.2s both}.success-text{margin-top:16px;color:#fff;font-size:14px;font-weight:600;text-align:center;background:rgba(128, 128, 128, 0.8);padding:12px 20px;border-radius:20px;max-width:300px;animation:fadeInUp 0.5s ease-out 0.4s both}@keyframes showSuccessMessage{0%{opacity:0;transform:translate(-50%, -50%) scale(0.5)}15%{opacity:1;transform:translate(-50%, -50%) scale(1)}85%{opacity:1;transform:translate(-50%, -50%) scale(1)}100%{opacity:0;transform:translate(-50%, -50%) scale(0.9)}}@keyframes bounceSuccess{0%{transform:scale(0)}50%{transform:scale(1.1)}100%{transform:scale(1)}}@keyframes drawCheck{0%{width:0;height:0}50%{width:20px;height:0}100%{width:20px;height:35px}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}100%{opacity:1;transform:translateY(0)}}.skip-button{position:absolute;bottom:20px;left:50%;transform:translateX(-50%);z-index:25;pointer-events:auto;background:#fff;color:#333;border:none;border-radius:25px;padding:12px 24px;font-size:14px;font-weight:600;cursor:pointer;transition:all 0.3s ease}.skip-button:hover{background:#f8f9fa}.skip-button:active{background:#e9ecef;transform:translateX(-50%) translateY(0)}.camera-controls{position:absolute;top:16px;right:16px;z-index:25;display:flex;gap:8px;pointer-events:auto}.camera-selector-button{height:32px;padding:0 10px;border:none;border-radius:8px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(12px);color:#ffffff;font-size:12px;font-weight:500;cursor:pointer;transition:all 0.2s ease;display:flex;align-items:center;justify-content:center;border:1px solid rgba(255, 255, 255, 0.1);white-space:nowrap;min-width:fit-content}.camera-selector-button:hover{background:rgba(0, 0, 0, 0.8);border-color:rgba(255, 255, 255, 0.2);transform:translateY(-1px)}.camera-selector-button:active{transform:translateY(0);background:rgba(0, 0, 0, 0.9)}.camera-selector-button:disabled,.camera-selector-button.loading{opacity:0.7;cursor:not-allowed;pointer-events:none}.camera-selector-button:disabled:hover,.camera-selector-button.loading:hover{transform:none;background:rgba(0, 0, 0, 0.6);border-color:rgba(255, 255, 255, 0.1)}.button-spinner{width:16px;height:16px;border:2px solid rgba(255, 255, 255, 0.3);border-top:2px solid #ffffff;border-radius:50%;animation:spin 1s linear infinite}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.camera-selector-dropdown{position:absolute;top:56px;right:16px;z-index:30;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;min-width:260px;max-width:300px;border:1px solid rgba(255, 255, 255, 0.1);overflow:hidden;pointer-events:auto;animation:slideInFromTop 0.3s ease-out}@keyframes slideInFromTop{0%{opacity:0;transform:translateY(-8px) scale(0.95)}100%{opacity:1;transform:translateY(0) scale(1)}}.camera-selector-header{display:flex;justify-content:space-between;align-items:center;padding:8px 12px;border-bottom:1px solid rgba(255, 255, 255, 0.1)}.camera-selector-header span{font-weight:500;color:#ffffff;font-size:13px;opacity:0.9}.close-selector{width:20px;height:20px;border:none;background:none;color:rgba(255, 255, 255, 0.7);font-size:16px;cursor:pointer;display:flex;align-items:center;justify-content:center;border-radius:4px;transition:all 0.2s ease}.close-selector:hover{background:rgba(255, 255, 255, 0.1);color:#ffffff}.camera-list{padding:4px 0;max-height:240px;overflow-y:auto}.camera-option{width:100%;padding:8px 12px;border:none;background:none;text-align:left;cursor:pointer;transition:all 0.2s ease;display:flex;justify-content:space-between;align-items:center;color:rgba(255, 255, 255, 0.9)}.camera-option:hover{background:rgba(255, 255, 255, 0.08)}.camera-option.selected{background:rgba(255, 255, 255, 0.12);color:#ffffff}.camera-label{font-size:13px;flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-right:8px;font-weight:400}.selected-indicator{font-size:14px;color:#ffffff;opacity:0.9}.device-info{padding:6px 12px;border-top:1px solid rgba(255, 255, 255, 0.1);background:rgba(255, 255, 255, 0.05)}.device-info small{color:rgba(255, 255, 255, 0.6);font-size:11px;text-transform:capitalize;font-weight:400}@media (max-width: 480px){.camera-controls{top:12px;right:12px;gap:6px}.camera-selector-button{height:36px;padding:0 12px;font-size:11px;border-radius:6px}.camera-selector-dropdown{right:12px;top:48px;min-width:240px;max-width:calc(100vw - 24px)}.camera-selector-header{padding:6px 10px}.camera-option{padding:6px 10px}.device-info{padding:4px 10px}}.watermark{position:absolute;bottom:12px;right:12px;z-index:15;pointer-events:none;opacity:0.7}.watermark img{height:24px;width:auto;filter:drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))}.component-status{position:absolute;top:16px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);display:flex;align-items:center;gap:6px;padding:6px 10px;z-index:40;height:32px;width:fit-content;animation:slideInFromTop 0.3s ease-out}.status-spinner{width:16px;height:16px;border:1px solid rgba(255, 255, 255, 0.3);border-top:1px solid #ffffff;border-radius:50%;animation:statusSpin 1s linear infinite;flex-shrink:0}.status-content{display:flex;flex-direction:column;gap:1px}.status-message{color:#ffffff;font-size:12px;font-weight:500;margin:0}.status-description{color:rgba(255, 255, 255, 0.7);font-size:10px;line-height:1.2;margin:0}@keyframes statusSpin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}@media (max-width: 480px){.component-status{top:12px;left:12px;padding:4px 8px;gap:4px;height:28px;border-radius:8px}.status-spinner{width:14px;height:14px}.status-message{font-size:11px}.status-description{font-size:9px}}.loading-overlay{position:absolute;top:0;left:0;width:100%;height:100%;background:rgba(0, 0, 0, 0.85);backdrop-filter:blur(4px);display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;border-radius:8px}.loading-spinner{width:50px;height:50px;border:3px solid rgba(255, 255, 255, 0.15);border-top:3px solid #28a745;border-radius:50%;animation:spin 1s ease-in-out infinite;margin-bottom:16px}.loading-text{color:#ffffff;font-size:14px;font-weight:500;text-align:center;opacity:0.9;margin-bottom:4px}.loading-description{color:rgba(255, 255, 255, 0.7);font-size:12px;text-align:center;opacity:0.8}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.performance-monitor{position:absolute;top:70px;left:16px;background:rgba(0, 0, 0, 0.25);backdrop-filter:blur(20px);border-radius:12px;border:1px solid rgba(255, 255, 255, 0.1);z-index:35;width:fit-content;animation:slideInFromLeft 0.3s ease-out;transition:all 0.3s ease}@keyframes slideInFromLeft{0%{opacity:0;transform:translateX(-20px) scale(0.95)}100%{opacity:1;transform:translateX(0) scale(1)}}.performance-expanded{padding:6px 10px}.metrics-row{display:flex;gap:8px;margin-bottom:4px}.metrics-row:last-child{margin-bottom:0}.metric-compact{display:flex;flex-direction:column;align-items:center;gap:2px;min-width:50px}.metric-label{font-size:9px;color:rgba(255, 255, 255, 0.6);font-weight:500;text-transform:uppercase;letter-spacing:0.3px}.metric-value{font-size:10px;font-weight:600;font-family:'Monaco', 'Menlo', 'Consolas', monospace;padding:2px 4px;border-radius:3px;text-align:center;white-space:nowrap}.metric-value.good{color:#4ade80;background:rgba(74, 222, 128, 0.1);border:1px solid rgba(74, 222, 128, 0.2)}.metric-value.warning{color:#fbbf24;background:rgba(251, 191, 36, 0.1);border:1px solid rgba(251, 191, 36, 0.2)}.metric-value.danger{color:#f87171;background:rgba(248, 113, 113, 0.1);border:1px solid rgba(248, 113, 113, 0.2)}@media (max-width: 480px){.performance-monitor{top:60px;left:12px;width:fit-content}.performance-expanded{padding:4px 8px}.metrics-row{gap:6px;margin-bottom:3px}.metric-compact{min-width:45px;gap:1px}.metric-label{font-size:8px}.metric-value{font-size:9px;padding:1px 3px}}@keyframes pulse{0%,100%{opacity:1}50%{opacity:0.7}}.metric-value.danger{animation:pulse 2s infinite}";const m=class{constructor(i){e(this,i);this.captureCompleted=t(this,"captureCompleted");this.isReady=t(this,"isReady")}get el(){return i(this)}debug=false;alignmentTolerance=10;maskSize=90;cropMargin=0;useDocumentClassification=false;preferredCamera="auto";captureDelay=1e3;enableQualityValidation=true;qualityThreshold=60;minQualityScore=45;minFocusScore=16;minBlurScore=22;maxReflectionScore=15;captureCompleted;isReady;detectionBoxes=[];sideAlignment={top:false,right:false,bottom:false,left:false};isMaskReady=false;shouldMirrorVideo=true;showCameraSelector=false;isSwitchingCamera=false;hasDocumentDetected=false;currentStatus={message:"Inicializando componente...",description:"Configurando servicios y cargando recursos",type:"initializing",isInitialized:false};qualityFeedback={message:"Analizando calidad...",score:0,hasIssues:false,canCapture:false};performanceData={fps:0,inferenceTime:0,memoryUsage:0,onnxLoadTime:0,frameProcessingTime:0,totalDetections:0,successfulDetections:0,detectionRate:0};serviceContainer;logger;eventBus;stateManager;cameraService;detectionService;videoRef;detectionContainer;videoStream;animationId;lastDetectedBox;startTime;hasScreenshotTaken=false;alignmentStartTime;alignmentTimer;performanceMetrics={fps:0,inferenceTime:0,memoryUsage:0,cpuUsage:0,onnxLoadTime:0,frameProcessingTime:0,totalDetections:0,successfulDetections:0,detectionRate:0,lastUpdateTime:0};performanceUpdateInterval;frameSkipCounter=0;FRAME_SKIP=2;consecutiveFailures=0;MAX_FAILURES=30;lastInferenceTime=0;MIN_INFERENCE_INTERVAL=50;async componentDidLoad(){this.updateStatus("Iniciando servicios...","Configurando módulos internos","initializing");await this.initializeServices();this.updateStatus("Configurando eventos...","Preparando comunicación entre servicios","initializing");await this.setupEventListeners();this.updateStatus("Inicializando cámara...","Detectando dispositivos disponibles","initializing");await this.initializeComponent();if(this.debug){this.initializePerformanceMonitor()}}async initializeServices(){const e={debug:this.debug,alignmentTolerance:this.alignmentTolerance,maskSize:this.maskSize,cropMargin:this.cropMargin,useDocumentClassification:this.useDocumentClassification,preferredCamera:this.preferredCamera,captureDelay:this.captureDelay,enableQualityValidation:this.enableQualityValidation,qualityThreshold:this.qualityThreshold,minQualityScore:this.minQualityScore,minFocusScore:this.minFocusScore,minBlurScore:this.minBlurScore,maxReflectionScore:this.maxReflectionScore};this.serviceContainer=new p(e);this.logger=this.serviceContainer.getLogger();this.eventBus=this.serviceContainer.getEventBus();this.stateManager=this.serviceContainer.getStateManager();this.cameraService=this.serviceContainer.getCameraService();this.detectionService=this.serviceContainer.getDetectionService();this.logger.state("SERVICIOS_INICIALIZADOS",{timestamp:Date.now()})}async setupEventListeners(){this.eventBus.on("state-changed",(e=>{this.handleStateChange(e)}));this.eventBus.on("camera-changed",(e=>{this.logger.state("CAMARA_CAMBIADA_EVENT",{cameraId:e})}));this.eventBus.on("error",(e=>{this.logger.error("Error en servicio:",e)}))}async initializeComponent(){this.logger.state("COMPONENTE_INICIALIZANDO",{debug:this.debug,maskSize:this.maskSize,cropMargin:this.cropMargin,useDocumentClassification:this.useDocumentClassification,preferredCamera:this.preferredCamera,captureDelay:this.captureDelay});this.validateProps();if(this.debug){this.stateManager.updateCaptureState({isLoading:true});await new Promise((e=>setTimeout(e,500)))}this.updateStatus("Detectando cámaras...","Buscando dispositivos de captura","initializing");await this.cameraService.detectDeviceType();await this.cameraService.enumerateDevices();this.updateStatus("Cargando modelo IA...","Preparando reconocimiento de documentos","initializing");await this.loadOnnxRuntime();this.initializeResizeObserver()}validateProps(){if(this.maskSize<50||this.maskSize>100){this.logger.warn(`Propiedad maskSize inválida. Valor: ${this.maskSize}, esperado: 50-100. Usando valor por defecto: 90`);this.maskSize=90}if(this.cropMargin<0||this.cropMargin>100){this.logger.warn(`Propiedad cropMargin inválida. Valor: ${this.cropMargin}, esperado: 0-100. Usando valor por defecto: 0`);this.cropMargin=0}const e=["auto","front","back"];if(!e.includes(this.preferredCamera)){this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${e.join(", ")}. Usando valor por defecto: 'auto'`);this.preferredCamera="auto"}if(this.captureDelay<0||this.captureDelay>1e4){this.logger.warn(`Propiedad captureDelay inválida. Valor: ${this.captureDelay}, esperado: 0-10000. Usando valor por defecto: 1000`);this.captureDelay=1e3}if(this.qualityThreshold<0||this.qualityThreshold>100){this.logger.warn(`Propiedad qualityThreshold inválida. Valor: ${this.qualityThreshold}, esperado: 0-100. Usando valor por defecto: 60`);this.qualityThreshold=60}if(this.minQualityScore<0||this.minQualityScore>100){this.logger.warn(`Propiedad minQualityScore inválida. Valor: ${this.minQualityScore}, esperado: 0-100. Usando valor por defecto: 45`);this.minQualityScore=45}if(this.minFocusScore<0||this.minFocusScore>100){this.logger.warn(`Propiedad minFocusScore inválida. Valor: ${this.minFocusScore}, esperado: 0-100. Usando valor por defecto: 16`);this.minFocusScore=16}if(this.minBlurScore<0||this.minBlurScore>200){this.logger.warn(`Propiedad minBlurScore inválida. Valor: ${this.minBlurScore}, esperado: 0-200. Usando valor por defecto: 22`);this.minBlurScore=22}if(this.maxReflectionScore<0||this.maxReflectionScore>100){this.logger.warn(`Propiedad maxReflectionScore inválida. Valor: ${this.maxReflectionScore}, esperado: 0-100. Usando valor por defecto: 15`);this.maxReflectionScore=15}}async loadOnnxRuntime(){if(!window.ort){this.updateStatus("Descargando librerías...","Obteniendo recursos de reconocimiento","initializing");const e=document.createElement("script");e.src="https://cdn.jsdelivr.net/npm/onnxruntime-web/dist/ort.min.js";document.head.appendChild(e);await new Promise((t=>{e.onload=()=>{setTimeout((()=>{this.finalizeInitialization();t(undefined)}),300)}}))}else{setTimeout((()=>{this.finalizeInitialization()}),300)}}finalizeInitialization(){this.stateManager.updateCaptureState({isLoading:false});this.currentStatus={message:"Listo para capturar",description:"",type:"ready",isInitialized:true};this.emitReadyEvent()}updateStatus(e,t,i="loading"){this.currentStatus={message:e,description:t,type:i,isInitialized:this.currentStatus.isInitialized}}emitReadyEvent(){const e=!!window.ort&&this.detectionService.isModelLoaded();this.isReady.emit(e);this.logger.state("COMPONENTE_LISTO",{ortLibraryLoaded:!!window.ort,modelPreloaded:this.detectionService.isModelLoaded(),isReady:e})}handleStateChange(e){}initializeResizeObserver(){if("ResizeObserver"in window&&this.detectionContainer){const e=new ResizeObserver((()=>{this.handleResize()}));e.observe(this.detectionContainer.parentElement)}}handleResize(){if(this.detectionContainer){const e=this.detectionContainer.parentElement;const t=e.getBoundingClientRect();this.updateMaskDimensions(t);this.logger.debug("Container redimensionado:",{width:t.width,height:t.height})}}updateMaskDimensions(e){if(!this.videoRef)return;const t=this.videoRef.videoWidth;const i=this.videoRef.videoHeight;if(t===0||i===0)return;const s=t/i;const a=e.width/e.height;let o,r;let n=0,c=0;if(s>a){o=e.width;r=e.width/s;c=(e.height-r)/2}else{r=e.height;o=e.height*s;n=(e.width-o)/2}const l=85.6/53.98;const d=r*l;let h,f;const p=this.maskSize/100;if(d<=o){f=r*p;h=f*l}else{h=o*p;f=h/l}const u=h/e.width*100;const m=f/e.height*100;const b=n+o/2;const g=c+r/2;const x=b/e.width*100;const y=g/e.height*100;this.el.style.setProperty("--mask-width",`${u}%`);this.el.style.setProperty("--mask-height",`${m}%`);this.el.style.setProperty("--mask-center-x",`${x}%`);this.el.style.setProperty("--mask-center-y",`${y}%`);this.isMaskReady=true;this.logger.state("DIMENSIONES_MASCARA_ACTUALIZADAS",{video:{width:t,height:i},displayed:{width:o,height:r},mask:{widthPercent:u,heightPercent:m},center:{x,y},offset:{x:n,y:c}})}async getCapturedImages(){const e=this.stateManager.getCaptureState();if(e.step!=="completed"){throw new Error("El proceso de captura no ha sido completado")}return this.stateManager.getCapturedImages()}async isProcessCompleted(){return this.stateManager.isProcessCompleted()}async startCapture(){await this.startDetection()}async stopCapture(){this.exitSession()}async resetCapture(){this.resetDetection()}async skipBackCapture(){const e=this.stateManager.getCaptureState();const t=this.stateManager.getCapturedImages();if(e.step==="back"&&t.front.fullFrame){this.completeProcess(true)}}async getStatus(){const e=this.stateManager.getCaptureState();const t=this.stateManager.getCapturedImages();return{isVideoActive:e.isVideoActive,captureStep:e.step,hasImages:!!(t.front.fullFrame||t.back.fullFrame),isProcessCompleted:this.stateManager.isProcessCompleted(),isModelPreloaded:this.detectionService.isModelLoaded()}}async preloadModel(){if(this.detectionService.isModelLoaded()){this.logger.state("MODELO_YA_PRECARGADO");this.updateStatus("Modelos ya cargados","","ready");return{success:true,message:"Model already loaded"}}try{const e=performance.now();this.updateStatus("Descargando modelo de detección...","Obteniendo red neuronal para reconocimiento de documentos","loading");this.stateManager.updateCaptureState({isLoading:true});await this.detectionService.loadModel();this.updateStatus("Cargando clasificador...","Preparando modelo de clasificación de tipos de documento","loading");await this.detectionService.loadClassificationModel();const t=performance.now();const i=t-e;if(this.debug){this.recordOnnxPerformance(i,0)}this.updateStatus("Optimizando modelos...","Configurando parámetros de rendimiento","loading");await new Promise((e=>setTimeout(e,300)));this.updateStatus("Modelos precargados","","ready");this.stateManager.updateCaptureState({isLoading:false});this.emitReadyEvent();this.logger.state("MODELOS_PRECARGADOS_EXITOSAMENTE",{loadTime:Math.round(i)});return{success:true,message:"Models preloaded successfully"}}catch(e){this.logger.error("Error al precargar modelos:",e);this.updateStatus("Error al cargar modelos","No se pudieron descargar los recursos necesarios","error");this.stateManager.updateCaptureState({isLoading:false});return{success:false,error:e.message}}}async getCameraInfo(){return this.cameraService.getCameraInfo()}async setPreferredCamera(e){this.preferredCamera=e;this.serviceContainer.updateConfig({preferredCamera:e});await this.cameraService.enumerateDevices();const t=this.stateManager.getCaptureState();if(t.isVideoActive){const e=this.cameraService.getSelectedCameraId();if(e){await this.cameraService.switchCamera(e)}}return{success:true,selectedCamera:this.cameraService.getSelectedCameraId(),availableCameras:this.cameraService.getAvailableCameras().length}}async setCaptureDelay(e){if(e<0||e>1e4){throw new Error("Capture delay must be between 0 and 10000 milliseconds")}this.captureDelay=e;this.serviceContainer.updateConfig({captureDelay:e});return{success:true,captureDelay:this.captureDelay}}async getCaptureDelay(){return this.captureDelay}async setTorchEnabled(e){const t=await this.cameraService.setTorchEnabled(e,this.videoStream);return{success:t,enabled:t?e:false}}async focusAtPoint(e,t){const i=await this.cameraService.focusAtPoint(e,t,this.videoStream);return{success:i,coordinates:{x:e,y:t}}}async getImageQuality(){if(!this.videoRef||!this.detectionService.isModelLoaded()){return null}try{const e=this.detectionService.validateImageQuality(this.videoRef);return{qualityScore:e.qualityScore,overallQuality:e.overallQuality,issues:e.issues,recommendations:e.recommendations,canCapture:this.detectionService.isImageQualityAcceptable(e)}}catch(e){this.logger.error("Error al analizar calidad de imagen:",e);return null}}async setQualityThresholds(e){if(e.minQualityScore!==undefined&&(e.minQualityScore<0||e.minQualityScore>100)){throw new Error("minQualityScore must be between 0 and 100")}if(e.minFocusScore!==undefined&&(e.minFocusScore<0||e.minFocusScore>100)){throw new Error("minFocusScore must be between 0 and 100")}if(e.minBlurScore!==undefined&&(e.minBlurScore<0||e.minBlurScore>200)){throw new Error("minBlurScore must be between 0 and 200")}if(e.maxReflectionScore!==undefined&&(e.maxReflectionScore<0||e.maxReflectionScore>100)){throw new Error("maxReflectionScore must be between 0 and 100")}if(e.minQualityScore!==undefined)this.minQualityScore=e.minQualityScore;if(e.minFocusScore!==undefined)this.minFocusScore=e.minFocusScore;if(e.minBlurScore!==undefined)this.minBlurScore=e.minBlurScore;if(e.maxReflectionScore!==undefined)this.maxReflectionScore=e.maxReflectionScore;this.detectionService.updateQualityThresholds(e);return{success:true,thresholds:this.detectionService.getQualityThresholds()}}async getQualityThresholds(){return{minQualityScore:this.minQualityScore,minFocusScore:this.minFocusScore,minBlurScore:this.minBlurScore,maxReflectionScore:this.maxReflectionScore}}async startDetection(){this.logger.state("INICIANDO_DETECCION");try{if(!this.detectionService.isModelLoaded()){const e=performance.now();this.updateStatus("Cargando modelo de detección...","Descargando red neuronal para reconocimiento","loading");this.stateManager.updateCaptureState({isLoading:true});await this.detectionService.loadModel();this.updateStatus("Cargando clasificador...","Preparando modelo de clasificación de documentos","loading");await this.detectionService.loadClassificationModel();const t=performance.now();const i=t-e;if(this.debug){this.recordOnnxPerformance(i,0)}this.logger.state("MODELOS_CARGADOS_EN_DETECCION",{loadTime:Math.round(i)})}this.updateStatus("Detectando cámaras...","Buscando dispositivos de captura disponibles","loading");await this.cameraService.enumerateDevices();this.updateStatus("Configurando cámara...","Estableciendo resolución y parámetros óptimos","loading");const e=await this.cameraService.setupCamera();this.updateStatus("Captura activa","Buscando documento en el marco de captura","active");await this.initializeVideoStream(e);if(this.detectionContainer){const e=this.detectionContainer.parentElement;const t=e.getBoundingClientRect();this.updateMaskDimensions(t)}this.startTime=Date.now();this.stateManager.updateCaptureState({isLoading:false});this.detectFrame()}catch(e){this.logger.error("Error al inicializar detección:",e);this.updateStatus("Error al iniciar captura","No se pudo completar la inicialización","error");this.stateManager.updateCaptureState({isLoading:false})}}async initializeVideoStream(e){if(this.videoRef){this.videoRef.srcObject=e;this.videoStream=e;const t=this.cameraService.isRearCamera(e);this.shouldMirrorVideo=!t;this.logger.state("CAMARA_CONFIGURADA",{isRearCamera:t,shouldMirrorVideo:this.shouldMirrorVideo});return new Promise((e=>{this.videoRef.onloadedmetadata=async()=>{await this.videoRef.play();this.stateManager.updateCaptureState({isVideoActive:true});e()}}))}else{throw new Error("Video element not available")}}async detectFrame(){try{const e=performance.now();const t=this.stateManager.getCaptureState();if(!this.videoRef||!this.detectionContainer||!this.detectionService.isModelLoaded())return;if(t.isDetectionPaused){if(t.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.frameSkipCounter++;if(this.frameSkipCounter<=this.FRAME_SKIP){if(t.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.frameSkipCounter=0;const i=Date.now();if(i-this.lastInferenceTime<this.MIN_INFERENCE_INTERVAL){if(t.step!=="completed"){this.animationId=requestAnimationFrame((()=>this.detectFrame()))}return}this.lastInferenceTime=i;const s=performance.now();const a=this.detectionService.preprocess(this.videoRef);let o;let r=null;let n=true;if(this.enableQualityValidation){const e=await this.detectionService.runInferenceWithQuality(a,this.videoRef);o=e.detections;r=e.qualityResult;n=e.canCapture;this.qualityFeedback={message:e.feedback,score:r.qualityScore,hasIssues:r.issues.length>0,canCapture:n}}else{o=await this.detectionService.runInference(a);const e=this.detectionService.getQuickQualityFeedback(this.videoRef);this.qualityFeedback={message:e.feedback,score:0,hasIssues:e.hasBlur||e.hasReflections||!e.isFocused,canCapture:true}}const c=performance.now()-s;if(this.debug){this.recordOnnxPerformance(0,c)}if(this.startTime&&Date.now()-this.startTime<5e3){o.forEach((e=>{const i=this.detectionService.isCardInFrame(e);const s=i?e.score*1.2:e.score;if(s>t.bestScore){this.stateManager.updateCaptureState({bestScore:s})}}))}this.hasDocumentDetected=o.length>0;if(o.length===0){this.consecutiveFailures++}else{this.consecutiveFailures=0}if(this.debug){this.updateDetectionBoxes(o)}else{this.detectionBoxes=[]}this.updateMaskColor(o);if(this.debug){const t=performance.now();const i=t-e;this.recordFrameProcessing(i,o.length)}if(t.step!=="completed"){if(this.consecutiveFailures>this.MAX_FAILURES){setTimeout((()=>this.detectFrame()),200)}else{this.animationId=requestAnimationFrame((()=>this.detectFrame()))}}}catch(e){this.logger.error("Error en inferencia de modelo:",e);const t=this.stateManager.getCaptureState();if(t.step!=="completed"){setTimeout((()=>this.detectFrame()),100)}}}disconnectedCallback(){this.cleanup()}cleanup(){if(this.animationId){cancelAnimationFrame(this.animationId)}if(this.videoStream){this.videoStream.getTracks().forEach((e=>e.stop()))}if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}if(this.performanceUpdateInterval){clearInterval(this.performanceUpdateInterval);this.performanceUpdateInterval=undefined}this.detectionBoxes=[];this.alignmentStartTime=undefined;this.hasDocumentDetected=false;this.serviceContainer?.cleanup()}render(){const e=this.stateManager?.getCaptureState()||{isVideoActive:false,showFlipAnimation:false,showSuccessAnimation:false,step:"front",isCapturing:false};const t=this.cameraService?.getCameraInfo()||{availableCameras:[],selectedCameraId:null,deviceType:"desktop"};return s("div",{key:"d71fc140c7fc87160ceaf479f9b9beae7685e9bc",class:"detector-container"},s("div",{key:"d83347ab6ccacfe940fb66d17adc21cff126d875",class:"video-container"},s("video",{key:"fb69de65e8133c7936cfb03ec86acdf89d2a8112",ref:e=>this.videoRef=e,autoplay:true,muted:true,playsinline:true,class:this.shouldMirrorVideo?"mirror":"",style:{display:e.isVideoActive?"block":"none"}}),s("div",{key:"c957341c1a750a1732afd6bb1045c1ba9bb2993d",ref:e=>this.detectionContainer=e,class:`detection-overlay ${this.shouldMirrorVideo?"mirror":""}`},this.debug&&this.detectionBoxes.map(((e,t)=>s("div",{key:t,class:"detection-box",style:{position:"absolute",left:`${e.x}px`,top:`${e.y}px`,width:`${e.w}px`,height:`${e.h}px`,border:"2px solid #32406C",pointerEvents:"none",boxSizing:"border-box"}})))),this.isMaskReady&&s("div",{key:"cf81504f7f129a2bb2789dd7addfe8d365fd7973",class:"overlay-mask"},s("div",{key:"b0f8ab1e02d1731295b95cbca4b44be430c6104d",class:"card-outline"},s("div",{key:"fadb33b8dc3c2cbfbb78aa0ff4d273b2b26a3565",class:"side side-top"}),s("div",{key:"3f3ca187195c78f2c3daffa481cc275f970c68a5",class:"side side-right"}),s("div",{key:"1e6bac145a85bbee2dab24da81b8064bc4ac282b",class:"side side-bottom"}),s("div",{key:"9bef1cd7afcef6cb1975a1103ec57d33d89f7640",class:"side side-left"}),!e.showFlipAnimation&&!e.showSuccessAnimation&&s("div",{key:"9198d8b8fb1f4a17ec615943a09844f47a639048",class:"guide-text"},this.enableQualityValidation&&this.hasDocumentDetected&&this.qualityFeedback.message?this.qualityFeedback.message:"Alinee su identificación con el marco"),this.enableQualityValidation&&this.hasDocumentDetected&&e.isVideoActive&&!e.showFlipAnimation&&!e.showSuccessAnimation&&s("div",{key:"04afa661c1d988d9bedb48c78672de233dd49f9b",class:`quality-indicator ${this.qualityFeedback.hasIssues?"warning":"good"}`},s("div",{key:"bc789e19894de1d3dfd4a232e05e612d804e0e6c",class:"quality-score"},this.qualityFeedback.score>0?`${this.qualityFeedback.score}%`:""),s("div",{key:"0750f5e5dfdb7a7c054d01965146d34a5bb4485a",class:`quality-status ${this.qualityFeedback.canCapture?"ready":"not-ready"}`},this.qualityFeedback.canCapture?"✓":"!"))),e.step==="back"&&!e.showFlipAnimation&&!e.showSuccessAnimation&&s("button",{key:"cbe391726b5d62acbb466c36b135e0556fc488f7",class:"skip-button",onClick:()=>this.skipBackCapture(),type:"button"},"Saltar reverso"),e.isVideoActive&&s("div",{key:"929f8fe054b30e3c30bf066319e957a633fa587c",class:"camera-controls"},s("button",{key:"b4f68dd3a6865cba49c3f5d38c43874b7b9b364d",class:`camera-selector-button ${this.isSwitchingCamera?"loading":""}`,onClick:()=>this.toggleCameraSelector(),type:"button",title:"Seleccionar cámara",disabled:this.isSwitchingCamera},this.isSwitchingCamera?s("div",{class:"button-spinner"}):"Cámaras")),this.showCameraSelector&&t.availableCameras.length>0&&s("div",{key:"c9315ff70704fdc265af07bf765b6247814563e6",class:"camera-selector-dropdown"},s("div",{key:"f4950e7e3c3e279c48310a4049550f3143fb4d3f",class:"camera-selector-header"},s("span",{key:"4cfacf909549b0e18bd8ac6e54e127ce09b75335"},"Seleccionar Cámara"),s("button",{key:"13d7679c5235f41f0dbc38b9f397483cf4ec9ffd",class:"close-selector",onClick:()=>this.toggleCameraSelector(),type:"button"},"×")),s("div",{key:"6c97cb8ba9486c33a633901d9dd49765f87d92ed",class:"camera-list"},t.availableCameras.map((e=>s("button",{key:e.id,class:`camera-option ${t.selectedCameraId===e.id?"selected":""}`,onClick:()=>this.handleCameraSwitch(e.id),type:"button"},s("span",{class:"camera-label"},e.label||`Cámara ${t.availableCameras.indexOf(e)+1}`),t.selectedCameraId===e.id&&s("span",{class:"selected-indicator"},"✓"))))),s("div",{key:"35796316fc950b8491f6167303b549b098abbf58",class:"device-info"},s("small",{key:"83c59a8cb0c0b67a37163fe75c1f1f383fcb00f4"},"Dispositivo: ",t.deviceType)))),e.isCapturing&&s("div",{key:"be5b316abb21c06cf5bb69ed090d43d45537a9e6",class:"capture-animation"}),e.showFlipAnimation&&s("div",{key:"43e64fcc325c7c96871a99838c5fa094c6774af2",class:"flip-animation"},s("div",{key:"39223d9b593716e76912ade58b556c7212a7e05f",class:"id-card-icon"}),s("div",{key:"79463b43724c3c56c45bd5b41337117d7d415618",class:"flip-text"},"¡Voltea tu identificación!")),e.showSuccessAnimation&&s("div",{key:"7be8ca4d0bd59b1e4127254ff68e41321aa387cc",class:"success-animation"},s("div",{key:"03a3e625f622c546a3016f85e029f9ea165f65c3",class:"check-icon"}),s("div",{key:"9c63faad517dad4b2ede8ec5a0998ad0b5c807d5",class:"success-text"},"¡Proceso completado!")),s("div",{key:"94aa38c67fdaf328e74a2c1ec476987bf8e483d5",class:`component-status status-${this.currentStatus.type}`},(this.currentStatus.type==="loading"||this.currentStatus.type==="initializing")&&s("div",{key:"52a460f2fe11505158331cc06d7121db80bdfed9",class:"status-spinner"}),s("div",{key:"1eabfed00df31ff30fdf818f3d33cd837a7f31a5",class:"status-content"},s("div",{key:"4bdbadf18fc48f2fad5dafd9ddf4a78f0a81dbf5",class:"status-message"},this.currentStatus.message),this.currentStatus.description&&s("div",{key:"14c41346fc9fc306315cdda1c54ec1e828c38f62",class:"status-description"},this.currentStatus.description))),this.debug&&s("div",{key:"21fb0ca08547143648097f2aa4f3eb3ade73bce1",class:"performance-monitor"},s("div",{key:"88c990f42b5c87c9bc971acd228fc84bacec861b",class:"performance-expanded"},s("div",{key:"351215f4b8ab202b42a4c9b0bfa8665485469f64",class:"metrics-row"},s("div",{key:"28a2c5386ba99850f7dc41add6fb4ef073a6b8cb",class:"metric-compact"},s("span",{key:"7a2ab758f9baf1264cd4ad70ff30f42a35c41065",class:"metric-label"},"FPS"),s("span",{key:"1c4370d016f2bdcf61275b4869bddbd8109a7b2a",class:`metric-value ${this.performanceData.fps<15?"warning":this.performanceData.fps<10?"danger":"good"}`},this.performanceData.fps)),s("div",{key:"e79c27b4cbad3e70f2df917a5147dd125d51304d",class:"metric-compact"},s("span",{key:"aee4c178ae751cfe94735ef9fcb78f273f9cb885",class:"metric-label"},"MEM"),s("span",{key:"823e98dec413968ee5080b29839729e6ac9f91d2",class:`metric-value ${this.performanceData.memoryUsage>100?"warning":this.performanceData.memoryUsage>200?"danger":"good"}`},this.performanceData.memoryUsage,"MB"))),s("div",{key:"e29037f684c82579a711aff022060c97ab9d93cf",class:"metrics-row"},s("div",{key:"2917f3c4b026e3106fad741944e582aff36e10e0",class:"metric-compact"},s("span",{key:"e8783e8e2b18b29b37342eea376a75f257a46850",class:"metric-label"},"INF"),s("span",{key:"30cdc1db3189135bc772aab5c31e081294ebd431",class:`metric-value ${this.performanceData.inferenceTime>100?"warning":this.performanceData.inferenceTime>200?"danger":"good"}`},this.performanceData.inferenceTime,"ms")),s("div",{key:"c481ec26394e35efe38047e5fa1b835e520f49b8",class:"metric-compact"},s("span",{key:"c806cae91f3fcad896bd6053b6a0391ab518ab6f",class:"metric-label"},"FRAME"),s("span",{key:"af9996e2093c918ea903d036e637905baeef1aa2",class:`metric-value ${this.performanceData.frameProcessingTime>50?"warning":this.performanceData.frameProcessingTime>100?"danger":"good"}`},this.performanceData.frameProcessingTime,"ms"))),s("div",{key:"48422447a6d00f78a9f861bfc50de4ef5a628a57",class:"metrics-row"},s("div",{key:"c88a03fbff56f68796df33187256fd5a5a68f763",class:"metric-compact"},s("span",{key:"5e366c35865f8bf45aecac126ce98e0e17be0825",class:"metric-label"},"DET"),s("span",{key:"123570ac9ae59cf5ef1b992ea6c4563b753990c3",class:"metric-value good"},this.performanceData.successfulDetections,"/",this.performanceData.totalDetections)),s("div",{key:"dea3a496f84e80f9d6f27173c8fa2e4149bf8e0b",class:"metric-compact"},s("span",{key:"fe47d6c16ca84fff8824bef92d8ce9efe50dfa38",class:"metric-label"},"RATE"),s("span",{key:"873846eb42c1ed97f4e9493871e51741766c852f",class:`metric-value ${this.performanceData.detectionRate<30?"danger":this.performanceData.detectionRate<60?"warning":"good"}`},this.performanceData.detectionRate,"%"))))),s("div",{key:"b485b1d8fafee0314ffbf1c7934ffc9a3d4c6902",class:"watermark"},s("img",{key:"f5fae340c3e96ecafe26aa819dbc2411038aa953",src:"https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png",alt:"Powered by Jaak"}))))}updateDetectionBoxes(e){if(!this.videoRef||!this.detectionContainer)return;const t=this.videoRef.videoWidth;const i=this.videoRef.videoHeight;const s=this.detectionContainer.parentElement;const a=s.getBoundingClientRect();const o=a.width;const r=a.height;if(t===0||i===0)return;const n=t/i;const c=o/r;let l,d;let h=0,f=0;if(n>c){l=o;d=o/n;f=(r-d)/2}else{d=r;l=r*n;h=(o-l)/2}const p=320;const u=l/p;const m=d/p;this.detectionBoxes=e.map((e=>({x:e.x*u+h,y:e.y*m+f,w:e.w*u,h:e.h*m,score:e.score})))}updateMaskColor(e){const t=this.el.shadowRoot?.querySelector(".card-outline");const i=this.el.shadowRoot?.querySelectorAll(".corner");const s=this.el.shadowRoot?.querySelector(".side-top");const a=this.el.shadowRoot?.querySelector(".side-right");const o=this.el.shadowRoot?.querySelector(".side-bottom");const r=this.el.shadowRoot?.querySelector(".side-left");let n=null;let c={top:false,right:false,bottom:false,left:false};if(e.length>0){n=e.reduce(((e,t)=>t.score>e.score?t:e));const t={INPUT_SIZE:320,ID1_ASPECT_RATIO:85.6/53.98,shouldMirrorVideo:this.shouldMirrorVideo,alignmentTolerance:this.alignmentTolerance,maskSize:this.maskSize,videoRef:this.videoRef};c=this.detectionService.checkSideAlignment(n,t);this.sideAlignment=c}else{this.sideAlignment={top:false,right:false,bottom:false,left:false}}s?.classList.toggle("aligned",c.top);a?.classList.toggle("aligned",c.right);o?.classList.toggle("aligned",c.bottom);r?.classList.toggle("aligned",c.left);const l=this.detectionService.areAllSidesAligned(c);if(l&&n){t?.classList.add("perfect-match");i?.forEach((e=>e.classList.add("perfect-match")));const e=!this.enableQualityValidation||this.qualityFeedback.canCapture;this.logger.state("CAPTURE_EVALUATION",{allSidesAligned:true,hasScreenshotTaken:this.hasScreenshotTaken,qualityCheckPassed:e,enableQualityValidation:this.enableQualityValidation,qualityFeedback:this.qualityFeedback,captureDelay:this.captureDelay,alignmentStartTime:this.alignmentStartTime});if(!this.hasScreenshotTaken&&e){const e=Date.now();if(!this.alignmentStartTime){this.alignmentStartTime=e;this.logger.state("ALIGNMENT_TIMER_STARTED",{startTime:e})}const t=e-this.alignmentStartTime;this.logger.state("ALIGNMENT_DURATION_CHECK",{alignmentDuration:t,captureDelay:this.captureDelay,readyToCapture:t>=this.captureDelay});if(t>=this.captureDelay){this.logger.state("TRIGGERING_CAPTURE",{alignmentDuration:t,captureDelay:this.captureDelay,qualityScore:this.qualityFeedback.score});this.lastDetectedBox=n;this.takeScreenshot().catch((e=>{this.logger.error("Error al tomar captura de pantalla:",e)}));this.hasScreenshotTaken=true;this.alignmentStartTime=undefined;setTimeout((()=>{this.hasScreenshotTaken=false}),2e3)}}else if(!e){this.logger.state("QUALITY_CHECK_FAILED",{enableQualityValidation:this.enableQualityValidation,canCapture:this.qualityFeedback.canCapture,qualityScore:this.qualityFeedback.score,hasIssues:this.qualityFeedback.hasIssues});this.alignmentStartTime=undefined;t?.classList.add("quality-warning")}}else{t?.classList.remove("perfect-match");i?.forEach((e=>e.classList.remove("perfect-match")));if(this.alignmentStartTime){this.alignmentStartTime=undefined}if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}}}async takeScreenshot(){if(!this.videoRef||!this.lastDetectedBox)return;this.logger.state("INICIANDO_CAPTURA",{captureStep:this.stateManager.getCaptureState().step,detectedBox:this.lastDetectedBox,videoResolution:{width:this.videoRef.videoWidth,height:this.videoRef.videoHeight}});this.stateManager.updateCaptureState({isCapturing:true});this.triggerCaptureAnimation();const e=document.createElement("canvas");e.width=this.videoRef.videoWidth;e.height=this.videoRef.videoHeight;const t=e.getContext("2d",{alpha:false});t.drawImage(this.videoRef,0,0,e.width,e.height);const i=320;const s=this.videoRef.videoWidth/i;const a=this.videoRef.videoHeight/i;const o=Math.max(0,this.lastDetectedBox.x*s-this.cropMargin);const r=Math.max(0,this.lastDetectedBox.y*a-this.cropMargin);const n=Math.min(this.lastDetectedBox.w*s+2*this.cropMargin,this.videoRef.videoWidth-o);const c=Math.min(this.lastDetectedBox.h*a+2*this.cropMargin,this.videoRef.videoHeight-r);const l=document.createElement("canvas");l.width=n;l.height=c;const d=l.getContext("2d",{alpha:false});d.drawImage(this.videoRef,o,r,n,c,0,0,n,c);const h=this.stateManager.getCaptureState();if(h.step==="front"){this.stateManager.setCapturedImages({front:{fullFrame:e.toDataURL("image/png"),cropped:l.toDataURL("image/png")}});if(this.useDocumentClassification){const e=await this.detectionService.classifyDocument(l);if(e&&e.class==="passport"){this.logger.state("PASAPORTE_DETECTADO_SALTANDO_REVERSO",{classification:e?.class});this.completeProcess(true);return}}this.stateManager.updateCaptureState({step:"back",isDetectionPaused:true,showFlipAnimation:true});setTimeout((()=>{this.stateManager.updateCaptureState({showFlipAnimation:false,isDetectionPaused:false})}),3e3)}else if(h.step==="back"){this.stateManager.setCapturedImages({back:{fullFrame:e.toDataURL("image/png"),cropped:l.toDataURL("image/png")}});this.completeProcess(false)}}triggerCaptureAnimation(){const e=this.el.shadowRoot?.querySelector(".card-outline");e?.classList.add("capturing");setTimeout((()=>{this.stateManager.updateCaptureState({isCapturing:false});e?.classList.remove("capturing")}),600)}completeProcess(e=false){this.stateManager.updateCaptureState({step:"completed",showSuccessAnimation:true});const t=this.stateManager.getCapturedImages();t.metadata.processCompleted=true;t.metadata.backCaptureSkipped=e;this.stateManager.setCapturedImages(t);this.stopDetection();this.updateStatus("Proceso completado",`${t.metadata.totalImages} imágenes capturadas exitosamente`,"ready");const i={...t,timestamp:(new Date).toISOString()};this.captureCompleted.emit(i);setTimeout((()=>{this.stateManager.updateCaptureState({showSuccessAnimation:false})}),3e3);this.logger.state("PROCESO_COMPLETADO",{skippedBack:e,totalImages:t.metadata.totalImages,timestamp:(new Date).toISOString()})}stopDetection(){if(this.animationId){cancelAnimationFrame(this.animationId);this.animationId=undefined}this.detectionBoxes=[];this.logger.state("DETECTOR_DETENIDO",{timestamp:Date.now()})}toggleCameraSelector(){if(this.isSwitchingCamera)return;this.showCameraSelector=!this.showCameraSelector}async handleCameraSwitch(e){if(this.isSwitchingCamera)return;try{this.showCameraSelector=false;this.isSwitchingCamera=true;this.logger.state("INICIANDO_CAMBIO_CAMARA",{from:this.cameraService.getSelectedCameraId(),to:e});if(this.videoStream){this.videoStream.getTracks().forEach((e=>e.stop()))}await this.cameraService.switchCamera(e);const t=await this.cameraService.setupCamera();await this.initializeVideoStream(t);this.logger.state("CAMBIO_CAMARA_EXITOSO",{newCameraId:e,isRearCamera:this.cameraService.isRearCamera(t)})}catch(e){this.logger.error("Error al cambiar cámara:",e);try{const e=await this.cameraService.setupCamera();await this.initializeVideoStream(e)}catch(e){this.logger.error("Error al restaurar cámara anterior:",e);this.updateStatus("Error al cambiar cámara","No se pudo completar el cambio de dispositivo","error")}}finally{this.isSwitchingCamera=false}}resetDetection(){const e=this.stateManager.getCaptureState();const t=e.isVideoActive;this.stateManager.reset();if(t){this.stateManager.updateCaptureState({isVideoActive:true})}this.hasScreenshotTaken=false;this.startTime=Date.now();this.frameSkipCounter=0;this.consecutiveFailures=0;this.lastInferenceTime=0;this.detectionBoxes=[];this.alignmentStartTime=undefined;this.hasDocumentDetected=false;if(this.alignmentTimer){clearTimeout(this.alignmentTimer);this.alignmentTimer=undefined}if(t&&this.detectionService.isModelLoaded()){this.updateStatus("Captura reiniciada","Buscando documento en el marco de captura","active");this.detectFrame()}else{this.updateStatus("Listo para capturar","","ready")}}exitSession(){if(this.videoStream){this.videoStream.getTracks().forEach((e=>e.stop()));this.videoStream=undefined;this.stateManager.updateCaptureState({isVideoActive:false,isLoading:false})}this.isMaskReady=false;this.updateStatus("Sesión finalizada","","ready");this.detectionBoxes=[];this.cleanup()}initializePerformanceMonitor(){this.performanceMetrics.lastUpdateTime=performance.now();this.performanceUpdateInterval=window.setInterval((()=>{this.updatePerformanceMetrics()}),500);this.logger.debug("Monitor de performance inicializado")}updatePerformanceMetrics(){const e=performance.now();const t=e-this.performanceMetrics.lastUpdateTime;if(t>0){this.performanceMetrics.fps=Math.round(1e3/(t/this.frameSkipCounter||1))}if("memory"in performance){const e=performance.memory;this.performanceMetrics.memoryUsage=Math.round(e.usedJSHeapSize/1048576)}if(this.performanceMetrics.totalDetections>0){this.performanceMetrics.successfulDetections=this.performanceMetrics.successfulDetections;const e=this.performanceMetrics.successfulDetections/this.performanceMetrics.totalDetections*100;this.performanceMetrics.detectionRate=Math.round(e)}this.performanceData={fps:this.performanceMetrics.fps,inferenceTime:this.performanceMetrics.inferenceTime,memoryUsage:this.performanceMetrics.memoryUsage,onnxLoadTime:this.performanceMetrics.onnxLoadTime,frameProcessingTime:this.performanceMetrics.frameProcessingTime,totalDetections:this.performanceMetrics.totalDetections,successfulDetections:this.performanceMetrics.successfulDetections,detectionRate:this.performanceMetrics.detectionRate};this.performanceMetrics.lastUpdateTime=e}recordOnnxPerformance(e,t){this.performanceMetrics.onnxLoadTime=Math.round(e);this.performanceMetrics.inferenceTime=Math.round(t)}recordFrameProcessing(e,t){this.performanceMetrics.frameProcessingTime=Math.round(e);this.performanceMetrics.totalDetections++;if(t>0){this.performanceMetrics.successfulDetections++}}};m.style=u;export{m as jaak_stamps};
|
|
2
|
-
//# sourceMappingURL=p-47f37982.entry.js.map
|