@jaak.ai/stamps 2.0.0-dev.39 → 2.0.0-dev.41

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.
Files changed (43) hide show
  1. package/README.md +4 -1
  2. package/dist/cjs/jaak-stamps-webcomponent.cjs.js +1 -1
  3. package/dist/cjs/jaak-stamps.cjs.entry.js +875 -13
  4. package/dist/cjs/jaak-stamps.cjs.entry.js.map +1 -1
  5. package/dist/cjs/jaak-stamps.entry.cjs.js.map +1 -1
  6. package/dist/cjs/loader.cjs.js +1 -1
  7. package/dist/collection/components/my-component/my-component.css +66 -0
  8. package/dist/collection/components/my-component/my-component.js +501 -10
  9. package/dist/collection/components/my-component/my-component.js.map +1 -1
  10. package/dist/collection/services/CameraService.js +161 -0
  11. package/dist/collection/services/CameraService.js.map +1 -1
  12. package/dist/collection/services/DetectionService.js +164 -1
  13. package/dist/collection/services/DetectionService.js.map +1 -1
  14. package/dist/collection/services/ImageQualityService.js +329 -0
  15. package/dist/collection/services/ImageQualityService.js.map +1 -0
  16. package/dist/collection/services/ServiceContainer.js +6 -1
  17. package/dist/collection/services/ServiceContainer.js.map +1 -1
  18. package/dist/collection/services/interfaces/ICameraService.js.map +1 -1
  19. package/dist/collection/services/interfaces/IDetectionService.js.map +1 -1
  20. package/dist/collection/services/interfaces/IImageQualityService.js +2 -0
  21. package/dist/collection/services/interfaces/IImageQualityService.js.map +1 -0
  22. package/dist/components/jaak-stamps.js +892 -14
  23. package/dist/components/jaak-stamps.js.map +1 -1
  24. package/dist/esm/jaak-stamps-webcomponent.js +1 -1
  25. package/dist/esm/jaak-stamps.entry.js +875 -13
  26. package/dist/esm/jaak-stamps.entry.js.map +1 -1
  27. package/dist/esm/loader.js +1 -1
  28. package/dist/jaak-stamps-webcomponent/jaak-stamps-webcomponent.esm.js +1 -1
  29. package/dist/jaak-stamps-webcomponent/jaak-stamps.entry.esm.js.map +1 -1
  30. package/dist/jaak-stamps-webcomponent/p-47f37982.entry.js +2 -0
  31. package/dist/jaak-stamps-webcomponent/p-47f37982.entry.js.map +1 -0
  32. package/dist/types/components/my-component/my-component.d.ts +48 -0
  33. package/dist/types/components.d.ts +65 -0
  34. package/dist/types/services/CameraService.d.ts +5 -0
  35. package/dist/types/services/DetectionService.d.ts +22 -2
  36. package/dist/types/services/ImageQualityService.d.ts +31 -0
  37. package/dist/types/services/ServiceContainer.d.ts +7 -0
  38. package/dist/types/services/interfaces/ICameraService.d.ts +2 -0
  39. package/dist/types/services/interfaces/IDetectionService.d.ts +13 -0
  40. package/dist/types/services/interfaces/IImageQualityService.d.ts +58 -0
  41. package/package.json +1 -1
  42. package/dist/jaak-stamps-webcomponent/p-043b1cfd.entry.js +0 -2
  43. package/dist/jaak-stamps-webcomponent/p-043b1cfd.entry.js.map +0 -1
@@ -8,6 +8,13 @@ export class JaakStamps {
8
8
  cropMargin = 0;
9
9
  useDocumentClassification = false;
10
10
  preferredCamera = 'auto';
11
+ captureDelay = 1000;
12
+ enableQualityValidation = true;
13
+ qualityThreshold = 60;
14
+ minQualityScore = 45;
15
+ minFocusScore = 16;
16
+ minBlurScore = 22;
17
+ maxReflectionScore = 15;
11
18
  captureCompleted;
12
19
  isReady;
13
20
  // State derived from services
@@ -19,12 +26,19 @@ export class JaakStamps {
19
26
  shouldMirrorVideo = true;
20
27
  showCameraSelector = false;
21
28
  isSwitchingCamera = false;
29
+ hasDocumentDetected = false;
22
30
  currentStatus = {
23
31
  message: 'Inicializando componente...',
24
32
  description: 'Configurando servicios y cargando recursos',
25
33
  type: 'initializing',
26
34
  isInitialized: false
27
35
  };
36
+ qualityFeedback = {
37
+ message: 'Analizando calidad...',
38
+ score: 0,
39
+ hasIssues: false,
40
+ canCapture: false
41
+ };
28
42
  performanceData = {
29
43
  fps: 0,
30
44
  inferenceTime: 0,
@@ -92,7 +106,14 @@ export class JaakStamps {
92
106
  maskSize: this.maskSize,
93
107
  cropMargin: this.cropMargin,
94
108
  useDocumentClassification: this.useDocumentClassification,
95
- preferredCamera: this.preferredCamera
109
+ preferredCamera: this.preferredCamera,
110
+ captureDelay: this.captureDelay,
111
+ enableQualityValidation: this.enableQualityValidation,
112
+ qualityThreshold: this.qualityThreshold,
113
+ minQualityScore: this.minQualityScore,
114
+ minFocusScore: this.minFocusScore,
115
+ minBlurScore: this.minBlurScore,
116
+ maxReflectionScore: this.maxReflectionScore
96
117
  };
97
118
  this.serviceContainer = new ServiceContainer(config);
98
119
  this.logger = this.serviceContainer.getLogger();
@@ -119,7 +140,8 @@ export class JaakStamps {
119
140
  maskSize: this.maskSize,
120
141
  cropMargin: this.cropMargin,
121
142
  useDocumentClassification: this.useDocumentClassification,
122
- preferredCamera: this.preferredCamera
143
+ preferredCamera: this.preferredCamera,
144
+ captureDelay: this.captureDelay
123
145
  });
124
146
  this.validateProps();
125
147
  if (this.debug) {
@@ -147,6 +169,30 @@ export class JaakStamps {
147
169
  this.logger.warn(`Propiedad preferredCamera inválida. Valor: ${this.preferredCamera}, esperado: ${validOptions.join(', ')}. Usando valor por defecto: 'auto'`);
148
170
  this.preferredCamera = 'auto';
149
171
  }
172
+ if (this.captureDelay < 0 || this.captureDelay > 10000) {
173
+ this.logger.warn(`Propiedad captureDelay inválida. Valor: ${this.captureDelay}, esperado: 0-10000. Usando valor por defecto: 1000`);
174
+ this.captureDelay = 1000;
175
+ }
176
+ if (this.qualityThreshold < 0 || this.qualityThreshold > 100) {
177
+ this.logger.warn(`Propiedad qualityThreshold inválida. Valor: ${this.qualityThreshold}, esperado: 0-100. Usando valor por defecto: 60`);
178
+ this.qualityThreshold = 60;
179
+ }
180
+ if (this.minQualityScore < 0 || this.minQualityScore > 100) {
181
+ this.logger.warn(`Propiedad minQualityScore inválida. Valor: ${this.minQualityScore}, esperado: 0-100. Usando valor por defecto: 45`);
182
+ this.minQualityScore = 45;
183
+ }
184
+ if (this.minFocusScore < 0 || this.minFocusScore > 100) {
185
+ this.logger.warn(`Propiedad minFocusScore inválida. Valor: ${this.minFocusScore}, esperado: 0-100. Usando valor por defecto: 16`);
186
+ this.minFocusScore = 16;
187
+ }
188
+ if (this.minBlurScore < 0 || this.minBlurScore > 200) {
189
+ this.logger.warn(`Propiedad minBlurScore inválida. Valor: ${this.minBlurScore}, esperado: 0-200. Usando valor por defecto: 22`);
190
+ this.minBlurScore = 22;
191
+ }
192
+ if (this.maxReflectionScore < 0 || this.maxReflectionScore > 100) {
193
+ this.logger.warn(`Propiedad maxReflectionScore inválida. Valor: ${this.maxReflectionScore}, esperado: 0-100. Usando valor por defecto: 15`);
194
+ this.maxReflectionScore = 15;
195
+ }
150
196
  }
151
197
  async loadOnnxRuntime() {
152
198
  if (!window.ort) {
@@ -371,6 +417,91 @@ export class JaakStamps {
371
417
  availableCameras: this.cameraService.getAvailableCameras().length
372
418
  };
373
419
  }
420
+ async setCaptureDelay(delay) {
421
+ if (delay < 0 || delay > 10000) {
422
+ throw new Error('Capture delay must be between 0 and 10000 milliseconds');
423
+ }
424
+ this.captureDelay = delay;
425
+ this.serviceContainer.updateConfig({ captureDelay: delay });
426
+ return {
427
+ success: true,
428
+ captureDelay: this.captureDelay
429
+ };
430
+ }
431
+ async getCaptureDelay() {
432
+ return this.captureDelay;
433
+ }
434
+ async setTorchEnabled(enabled) {
435
+ const torchEnabled = await this.cameraService.setTorchEnabled(enabled, this.videoStream);
436
+ return {
437
+ success: torchEnabled,
438
+ enabled: torchEnabled ? enabled : false
439
+ };
440
+ }
441
+ async focusAtPoint(x, y) {
442
+ const focused = await this.cameraService.focusAtPoint(x, y, this.videoStream);
443
+ return {
444
+ success: focused,
445
+ coordinates: { x, y }
446
+ };
447
+ }
448
+ async getImageQuality() {
449
+ if (!this.videoRef || !this.detectionService.isModelLoaded()) {
450
+ return null;
451
+ }
452
+ try {
453
+ const qualityResult = this.detectionService.validateImageQuality(this.videoRef);
454
+ return {
455
+ qualityScore: qualityResult.qualityScore,
456
+ overallQuality: qualityResult.overallQuality,
457
+ issues: qualityResult.issues,
458
+ recommendations: qualityResult.recommendations,
459
+ canCapture: this.detectionService.isImageQualityAcceptable(qualityResult)
460
+ };
461
+ }
462
+ catch (error) {
463
+ this.logger.error('Error al analizar calidad de imagen:', error);
464
+ return null;
465
+ }
466
+ }
467
+ async setQualityThresholds(thresholds) {
468
+ // Validate thresholds
469
+ if (thresholds.minQualityScore !== undefined && (thresholds.minQualityScore < 0 || thresholds.minQualityScore > 100)) {
470
+ throw new Error('minQualityScore must be between 0 and 100');
471
+ }
472
+ if (thresholds.minFocusScore !== undefined && (thresholds.minFocusScore < 0 || thresholds.minFocusScore > 100)) {
473
+ throw new Error('minFocusScore must be between 0 and 100');
474
+ }
475
+ if (thresholds.minBlurScore !== undefined && (thresholds.minBlurScore < 0 || thresholds.minBlurScore > 200)) {
476
+ throw new Error('minBlurScore must be between 0 and 200');
477
+ }
478
+ if (thresholds.maxReflectionScore !== undefined && (thresholds.maxReflectionScore < 0 || thresholds.maxReflectionScore > 100)) {
479
+ throw new Error('maxReflectionScore must be between 0 and 100');
480
+ }
481
+ // Update component properties
482
+ if (thresholds.minQualityScore !== undefined)
483
+ this.minQualityScore = thresholds.minQualityScore;
484
+ if (thresholds.minFocusScore !== undefined)
485
+ this.minFocusScore = thresholds.minFocusScore;
486
+ if (thresholds.minBlurScore !== undefined)
487
+ this.minBlurScore = thresholds.minBlurScore;
488
+ if (thresholds.maxReflectionScore !== undefined)
489
+ this.maxReflectionScore = thresholds.maxReflectionScore;
490
+ // Update detection service
491
+ this.detectionService.updateQualityThresholds(thresholds);
492
+ return {
493
+ success: true,
494
+ thresholds: this.detectionService.getQualityThresholds()
495
+ };
496
+ }
497
+ async getQualityThresholds() {
498
+ return {
499
+ minQualityScore: this.minQualityScore,
500
+ minFocusScore: this.minFocusScore,
501
+ minBlurScore: this.minBlurScore,
502
+ maxReflectionScore: this.maxReflectionScore
503
+ };
504
+ }
374
505
  // DETECTION METHODS
375
506
  async startDetection() {
376
507
  this.logger.state('INICIANDO_DETECCION');
@@ -472,7 +603,36 @@ export class JaakStamps {
472
603
  // Measure preprocessing and inference time
473
604
  const inferenceStartTime = performance.now();
474
605
  const inputTensor = this.detectionService.preprocess(this.videoRef);
475
- const detections = await this.detectionService.runInference(inputTensor);
606
+ // Enhanced detection with quality validation if enabled
607
+ let detections;
608
+ let qualityResult = null;
609
+ let canCapture = true;
610
+ if (this.enableQualityValidation) {
611
+ // Use enhanced detection method with quality validation
612
+ const enhancedResult = await this.detectionService.runInferenceWithQuality(inputTensor, this.videoRef);
613
+ detections = enhancedResult.detections;
614
+ qualityResult = enhancedResult.qualityResult;
615
+ canCapture = enhancedResult.canCapture;
616
+ // Update quality feedback state
617
+ this.qualityFeedback = {
618
+ message: enhancedResult.feedback,
619
+ score: qualityResult.qualityScore,
620
+ hasIssues: qualityResult.issues.length > 0,
621
+ canCapture: canCapture
622
+ };
623
+ }
624
+ else {
625
+ // Standard detection without quality validation
626
+ detections = await this.detectionService.runInference(inputTensor);
627
+ // Quick quality feedback for real-time display
628
+ const quickFeedback = this.detectionService.getQuickQualityFeedback(this.videoRef);
629
+ this.qualityFeedback = {
630
+ message: quickFeedback.feedback,
631
+ score: 0, // Not calculated in quick mode
632
+ hasIssues: quickFeedback.hasBlur || quickFeedback.hasReflections || !quickFeedback.isFocused,
633
+ canCapture: true // Allow capture without strict validation
634
+ };
635
+ }
476
636
  const inferenceTime = performance.now() - inferenceStartTime;
477
637
  // Record ONNX performance metrics
478
638
  if (this.debug) {
@@ -488,6 +648,8 @@ export class JaakStamps {
488
648
  }
489
649
  });
490
650
  }
651
+ // Update document detection state
652
+ this.hasDocumentDetected = detections.length > 0;
491
653
  // Adaptive frame rate
492
654
  if (detections.length === 0) {
493
655
  this.consecutiveFailures++;
@@ -549,6 +711,7 @@ export class JaakStamps {
549
711
  }
550
712
  this.detectionBoxes = [];
551
713
  this.alignmentStartTime = undefined;
714
+ this.hasDocumentDetected = false;
552
715
  this.serviceContainer?.cleanup();
553
716
  }
554
717
  render() {
@@ -567,7 +730,7 @@ export class JaakStamps {
567
730
  deviceType: 'desktop',
568
731
  preferredFacing: null
569
732
  };
570
- return (h("div", { key: '91be2bd01dfa62ef439ff4b3d029539248b69364', class: "detector-container" }, h("div", { key: '7dbfbe2b782a8d06e2303ec3edff4b5c68ba4444', class: "video-container" }, h("video", { key: 'a2b7ec84a2f49935a94f1afb12deb1137f472fcd', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: '63cf0b7a05fc6d604f3a273fd902717542ba47f5', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
733
+ return (h("div", { key: 'd71fc140c7fc87160ceaf479f9b9beae7685e9bc', class: "detector-container" }, h("div", { key: 'd83347ab6ccacfe940fb66d17adc21cff126d875', class: "video-container" }, h("video", { key: 'fb69de65e8133c7936cfb03ec86acdf89d2a8112', ref: el => this.videoRef = el, autoplay: true, muted: true, playsinline: true, class: this.shouldMirrorVideo ? 'mirror' : '', style: { display: captureState.isVideoActive ? 'block' : 'none' } }), h("div", { key: 'c957341c1a750a1732afd6bb1045c1ba9bb2993d', ref: el => this.detectionContainer = el, class: `detection-overlay ${this.shouldMirrorVideo ? 'mirror' : ''}` }, this.debug && this.detectionBoxes.map((box, index) => (h("div", { key: index, class: "detection-box", style: {
571
734
  position: 'absolute',
572
735
  left: `${box.x}px`,
573
736
  top: `${box.y}px`,
@@ -576,7 +739,9 @@ export class JaakStamps {
576
739
  border: '2px solid #32406C',
577
740
  pointerEvents: 'none',
578
741
  boxSizing: 'border-box'
579
- } })))), this.isMaskReady && (h("div", { key: '089227de9415e523e99261eeeca5dcb981816a83', class: "overlay-mask" }, h("div", { key: '846bd914025e8da92ca85381a566c6d93caea2ea', class: "card-outline" }, h("div", { key: '1f49ae76e9066a65e848e55e19839547d8b9bef0', class: "side side-top" }), h("div", { key: '5b69c6bcf604042f86383e9bf122204d4fe1aeb1', class: "side side-right" }), h("div", { key: '8aa4c1f09c8b7046a369ed8d7fae1a96a525f778', class: "side side-bottom" }), h("div", { key: 'd8826c0347a219c154703d165ee5b4ced33f7a3f', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '916e038d0d0f80971629916189ef39c2689e4e43', class: "guide-text" }, "Alinee su identificaci\u00F3n con el marco"))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("button", { key: '02b01dff08bdbf042c6df1403f955601964bff28', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (h("div", { key: 'cd88fd0567e5b792ddc623c281616ea35616f8f6', class: "camera-controls" }, h("button", { key: '9d2a63a53926d0c987e551bd49caa8143b4e15d4', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: '43e9ea946f88498082339de62cf54cba352e765e', class: "camera-selector-dropdown" }, h("div", { key: '9fe39e8fa32ee458e4261d3f0d8fd40d50fefcf4', class: "camera-selector-header" }, h("span", { key: 'edf45c7bd8c5a43df9aba3ff6310cc5d06bb1aa2' }, "Seleccionar C\u00E1mara"), h("button", { key: 'dd5d417bb5eadd3f3b488ecd901d8dfa075c29c8', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '8edcd693f137ddd4ada9654c01615a17c90cb9c3', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: 'b7f050513f25af03ca72a735bd8745f71a456d76', class: "device-info" }, h("small", { key: '34305a7ca3418d46bceb2a9923a664fd5a0062fa' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: '54ec511bd6d22c8c25eb41717abcebd89ed315f8', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '9392bccfd3576b1858610b543c0ac0b747cef153', class: "flip-animation" }, h("div", { key: '030dc63ea455afa24fd0b370425aae14ab322613', class: "id-card-icon" }), h("div", { key: '3f7d8985af2d6eaec21699b87d5aeb0b27d2d55e', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '0da0a234e87013fb2ccc652cb920318cf00b6733', class: "success-animation" }, h("div", { key: 'f6b62ff21e147c8b365ab8c88e42dcb106cb8743', class: "check-icon" }), h("div", { key: '8c8b56561234e140cd658c5fad252cd6a1e0251c', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '684119ec540276cc28a49724d6177c72aff74b02', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: 'abc9a89349b9d8d76e03c765aa0084ec364f73a8', class: "status-spinner" })), h("div", { key: '6903b83962ee971a95a18e9ac793d872a7ce4551', class: "status-content" }, h("div", { key: 'c01dd0268a223ee269b616cea19a9cdb69cc048f', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '1f6ebecc7a1d058c34aca5b4572ace8a81b5ab69', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: 'eff03d22449aafac6c986e71af2aafd487b1776d', class: "performance-monitor" }, h("div", { key: '66dfd57c92f7ee67e7c52293b3ad3f1105793e70', class: "performance-expanded" }, h("div", { key: '0d952f89275e551a1e4cdb9b215e1ba48776ebd4', class: "metrics-row" }, h("div", { key: '36fab2101078e4da16a3a3ac50d927077d9e0874', class: "metric-compact" }, h("span", { key: 'a694bf26ff69522a6462963d735ffa145513d84c', class: "metric-label" }, "FPS"), h("span", { key: '02a250b3863f8f158a4103e0817cf14accdb7b30', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'd6e849779f13ae0ee3641d98148f0ab151877157', class: "metric-compact" }, h("span", { key: '983411baa6e79e3bfe7ad277879361c023dc6d48', class: "metric-label" }, "MEM"), h("span", { key: 'eea7060b9cef780ed47a534b7bc69c94162b67d9', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'e0e5e80c208f1eadc606c20df844efcc66f6599c', class: "metrics-row" }, h("div", { key: 'd27ae06d877097c99c1796c36284427861ae0be3', class: "metric-compact" }, h("span", { key: '229837e3037ce64fc5930a5732ad6a0e323371e9', class: "metric-label" }, "INF"), h("span", { key: '82002332976cddf7dbb2aa6346ad9da0ce0901df', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: '243afc7933e169084eda28cca270198420a4341d', class: "metric-compact" }, h("span", { key: '834e9a69791abc42545dddc1c0de7372a3292d60', class: "metric-label" }, "FRAME"), h("span", { key: '9106f8989818aa9111d7571006224befe7837406', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: 'da911fc95ce6151fb5fb64b8d5df53d6b693ffef', class: "metrics-row" }, h("div", { key: 'c813a7152d51bd2402b9c2bdf5bd1fe09b6df7db', class: "metric-compact" }, h("span", { key: 'b5a7807764a897663ce9d37111188c26bcf2cb6d', class: "metric-label" }, "DET"), h("span", { key: '17ec09407ac24800e0ec965c7b3a037730a6afd4', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: '5aa0b6f4d1643e3ec224d1a9d89d4d37407d3c58', class: "metric-compact" }, h("span", { key: '6b8efdcf07e9eac7d5036a508804b017ccedaea9', class: "metric-label" }, "RATE"), h("span", { key: '038a5c3377185784c806c614f0c098e417360acf', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: '3317e18916b62bce70cc02540cfc274d588b466a', class: "watermark" }, h("img", { key: 'adf070f99c17c3fdfc3e2c69b1a63dfef66ad71e', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
742
+ } })))), this.isMaskReady && (h("div", { key: 'cf81504f7f129a2bb2789dd7addfe8d365fd7973', class: "overlay-mask" }, h("div", { key: 'b0f8ab1e02d1731295b95cbca4b44be430c6104d', class: "card-outline" }, h("div", { key: 'fadb33b8dc3c2cbfbb78aa0ff4d273b2b26a3565', class: "side side-top" }), h("div", { key: '3f3ca187195c78f2c3daffa481cc275f970c68a5', class: "side side-right" }), h("div", { key: '1e6bac145a85bbee2dab24da81b8064bc4ac282b', class: "side side-bottom" }), h("div", { key: '9bef1cd7afcef6cb1975a1103ec57d33d89f7640', class: "side side-left" }), !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '9198d8b8fb1f4a17ec615943a09844f47a639048', class: "guide-text" }, this.enableQualityValidation && this.hasDocumentDetected && this.qualityFeedback.message ?
743
+ this.qualityFeedback.message :
744
+ 'Alinee su identificación con el marco')), this.enableQualityValidation && this.hasDocumentDetected && captureState.isVideoActive && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("div", { key: '04afa661c1d988d9bedb48c78672de233dd49f9b', class: `quality-indicator ${this.qualityFeedback.hasIssues ? 'warning' : 'good'}` }, h("div", { key: 'bc789e19894de1d3dfd4a232e05e612d804e0e6c', class: "quality-score" }, this.qualityFeedback.score > 0 ? `${this.qualityFeedback.score}%` : ''), h("div", { key: '0750f5e5dfdb7a7c054d01965146d34a5bb4485a', class: `quality-status ${this.qualityFeedback.canCapture ? 'ready' : 'not-ready'}` }, this.qualityFeedback.canCapture ? '✓' : '!')))), captureState.step === 'back' && !captureState.showFlipAnimation && !captureState.showSuccessAnimation && (h("button", { key: 'cbe391726b5d62acbb466c36b135e0556fc488f7', class: "skip-button", onClick: () => this.skipBackCapture(), type: "button" }, "Saltar reverso")), captureState.isVideoActive && (h("div", { key: '929f8fe054b30e3c30bf066319e957a633fa587c', class: "camera-controls" }, h("button", { key: 'b4f68dd3a6865cba49c3f5d38c43874b7b9b364d', class: `camera-selector-button ${this.isSwitchingCamera ? 'loading' : ''}`, onClick: () => this.toggleCameraSelector(), type: "button", title: "Seleccionar c\u00E1mara", disabled: this.isSwitchingCamera }, this.isSwitchingCamera ? (h("div", { class: "button-spinner" })) : ('Cámaras')))), this.showCameraSelector && cameraInfo.availableCameras.length > 0 && (h("div", { key: 'c9315ff70704fdc265af07bf765b6247814563e6', class: "camera-selector-dropdown" }, h("div", { key: 'f4950e7e3c3e279c48310a4049550f3143fb4d3f', class: "camera-selector-header" }, h("span", { key: '4cfacf909549b0e18bd8ac6e54e127ce09b75335' }, "Seleccionar C\u00E1mara"), h("button", { key: '13d7679c5235f41f0dbc38b9f397483cf4ec9ffd', class: "close-selector", onClick: () => this.toggleCameraSelector(), type: "button" }, "\u00D7")), h("div", { key: '6c97cb8ba9486c33a633901d9dd49765f87d92ed', class: "camera-list" }, cameraInfo.availableCameras.map((camera) => (h("button", { key: camera.id, class: `camera-option ${cameraInfo.selectedCameraId === camera.id ? 'selected' : ''}`, onClick: () => this.handleCameraSwitch(camera.id), type: "button" }, h("span", { class: "camera-label" }, camera.label || `Cámara ${cameraInfo.availableCameras.indexOf(camera) + 1}`), cameraInfo.selectedCameraId === camera.id && (h("span", { class: "selected-indicator" }, "\u2713")))))), h("div", { key: '35796316fc950b8491f6167303b549b098abbf58', class: "device-info" }, h("small", { key: '83c59a8cb0c0b67a37163fe75c1f1f383fcb00f4' }, "Dispositivo: ", cameraInfo.deviceType)))))), captureState.isCapturing && (h("div", { key: 'be5b316abb21c06cf5bb69ed090d43d45537a9e6', class: "capture-animation" })), captureState.showFlipAnimation && (h("div", { key: '43e64fcc325c7c96871a99838c5fa094c6774af2', class: "flip-animation" }, h("div", { key: '39223d9b593716e76912ade58b556c7212a7e05f', class: "id-card-icon" }), h("div", { key: '79463b43724c3c56c45bd5b41337117d7d415618', class: "flip-text" }, "\u00A1Voltea tu identificaci\u00F3n!"))), captureState.showSuccessAnimation && (h("div", { key: '7be8ca4d0bd59b1e4127254ff68e41321aa387cc', class: "success-animation" }, h("div", { key: '03a3e625f622c546a3016f85e029f9ea165f65c3', class: "check-icon" }), h("div", { key: '9c63faad517dad4b2ede8ec5a0998ad0b5c807d5', class: "success-text" }, "\u00A1Proceso completado!"))), h("div", { key: '94aa38c67fdaf328e74a2c1ec476987bf8e483d5', class: `component-status status-${this.currentStatus.type}` }, (this.currentStatus.type === 'loading' || this.currentStatus.type === 'initializing') && (h("div", { key: '52a460f2fe11505158331cc06d7121db80bdfed9', class: "status-spinner" })), h("div", { key: '1eabfed00df31ff30fdf818f3d33cd837a7f31a5', class: "status-content" }, h("div", { key: '4bdbadf18fc48f2fad5dafd9ddf4a78f0a81dbf5', class: "status-message" }, this.currentStatus.message), this.currentStatus.description && (h("div", { key: '14c41346fc9fc306315cdda1c54ec1e828c38f62', class: "status-description" }, this.currentStatus.description)))), this.debug && (h("div", { key: '21fb0ca08547143648097f2aa4f3eb3ade73bce1', class: "performance-monitor" }, h("div", { key: '88c990f42b5c87c9bc971acd228fc84bacec861b', class: "performance-expanded" }, h("div", { key: '351215f4b8ab202b42a4c9b0bfa8665485469f64', class: "metrics-row" }, h("div", { key: '28a2c5386ba99850f7dc41add6fb4ef073a6b8cb', class: "metric-compact" }, h("span", { key: '7a2ab758f9baf1264cd4ad70ff30f42a35c41065', class: "metric-label" }, "FPS"), h("span", { key: '1c4370d016f2bdcf61275b4869bddbd8109a7b2a', class: `metric-value ${this.performanceData.fps < 15 ? 'warning' : this.performanceData.fps < 10 ? 'danger' : 'good'}` }, this.performanceData.fps)), h("div", { key: 'e79c27b4cbad3e70f2df917a5147dd125d51304d', class: "metric-compact" }, h("span", { key: 'aee4c178ae751cfe94735ef9fcb78f273f9cb885', class: "metric-label" }, "MEM"), h("span", { key: '823e98dec413968ee5080b29839729e6ac9f91d2', class: `metric-value ${this.performanceData.memoryUsage > 100 ? 'warning' : this.performanceData.memoryUsage > 200 ? 'danger' : 'good'}` }, this.performanceData.memoryUsage, "MB"))), h("div", { key: 'e29037f684c82579a711aff022060c97ab9d93cf', class: "metrics-row" }, h("div", { key: '2917f3c4b026e3106fad741944e582aff36e10e0', class: "metric-compact" }, h("span", { key: 'e8783e8e2b18b29b37342eea376a75f257a46850', class: "metric-label" }, "INF"), h("span", { key: '30cdc1db3189135bc772aab5c31e081294ebd431', class: `metric-value ${this.performanceData.inferenceTime > 100 ? 'warning' : this.performanceData.inferenceTime > 200 ? 'danger' : 'good'}` }, this.performanceData.inferenceTime, "ms")), h("div", { key: 'c481ec26394e35efe38047e5fa1b835e520f49b8', class: "metric-compact" }, h("span", { key: 'c806cae91f3fcad896bd6053b6a0391ab518ab6f', class: "metric-label" }, "FRAME"), h("span", { key: 'af9996e2093c918ea903d036e637905baeef1aa2', class: `metric-value ${this.performanceData.frameProcessingTime > 50 ? 'warning' : this.performanceData.frameProcessingTime > 100 ? 'danger' : 'good'}` }, this.performanceData.frameProcessingTime, "ms"))), h("div", { key: '48422447a6d00f78a9f861bfc50de4ef5a628a57', class: "metrics-row" }, h("div", { key: 'c88a03fbff56f68796df33187256fd5a5a68f763', class: "metric-compact" }, h("span", { key: '5e366c35865f8bf45aecac126ce98e0e17be0825', class: "metric-label" }, "DET"), h("span", { key: '123570ac9ae59cf5ef1b992ea6c4563b753990c3', class: "metric-value good" }, this.performanceData.successfulDetections, "/", this.performanceData.totalDetections)), h("div", { key: 'dea3a496f84e80f9d6f27173c8fa2e4149bf8e0b', class: "metric-compact" }, h("span", { key: 'fe47d6c16ca84fff8824bef92d8ce9efe50dfa38', class: "metric-label" }, "RATE"), h("span", { key: '873846eb42c1ed97f4e9493871e51741766c852f', class: `metric-value ${this.performanceData.detectionRate < 30 ? 'danger' : this.performanceData.detectionRate < 60 ? 'warning' : 'good'}` }, this.performanceData.detectionRate, "%")))))), h("div", { key: 'b485b1d8fafee0314ffbf1c7934ffc9a3d4c6902', class: "watermark" }, h("img", { key: 'f5fae340c3e96ecafe26aa819dbc2411038aa953', src: "https://storage.googleapis.com/jaak-static/commons/powered-by-jaak.png", alt: "Powered by Jaak" })))));
580
745
  }
581
746
  // Utility methods
582
747
  updateDetectionBoxes(boxes) {
@@ -648,15 +813,38 @@ export class JaakStamps {
648
813
  if (allSidesAligned && bestBox) {
649
814
  cardOutline?.classList.add('perfect-match');
650
815
  corners?.forEach(corner => corner.classList.add('perfect-match'));
651
- if (!this.hasScreenshotTaken) {
816
+ // Check quality validation before allowing capture
817
+ const qualityCheckPassed = !this.enableQualityValidation || this.qualityFeedback.canCapture;
818
+ // Debug logging
819
+ this.logger.state('CAPTURE_EVALUATION', {
820
+ allSidesAligned: true,
821
+ hasScreenshotTaken: this.hasScreenshotTaken,
822
+ qualityCheckPassed,
823
+ enableQualityValidation: this.enableQualityValidation,
824
+ qualityFeedback: this.qualityFeedback,
825
+ captureDelay: this.captureDelay,
826
+ alignmentStartTime: this.alignmentStartTime
827
+ });
828
+ if (!this.hasScreenshotTaken && qualityCheckPassed) {
652
829
  const currentTime = Date.now();
653
830
  // Initialize alignment start time if not set
654
831
  if (!this.alignmentStartTime) {
655
832
  this.alignmentStartTime = currentTime;
833
+ this.logger.state('ALIGNMENT_TIMER_STARTED', { startTime: currentTime });
656
834
  }
657
- // Check if document has been aligned for 1 second
835
+ // Check if document has been aligned for the configured delay
658
836
  const alignmentDuration = currentTime - this.alignmentStartTime;
659
- if (alignmentDuration >= 1000) {
837
+ this.logger.state('ALIGNMENT_DURATION_CHECK', {
838
+ alignmentDuration,
839
+ captureDelay: this.captureDelay,
840
+ readyToCapture: alignmentDuration >= this.captureDelay
841
+ });
842
+ if (alignmentDuration >= this.captureDelay) {
843
+ this.logger.state('TRIGGERING_CAPTURE', {
844
+ alignmentDuration,
845
+ captureDelay: this.captureDelay,
846
+ qualityScore: this.qualityFeedback.score
847
+ });
660
848
  this.lastDetectedBox = bestBox;
661
849
  this.takeScreenshot().catch(error => {
662
850
  this.logger.error('Error al tomar captura de pantalla:', error);
@@ -668,6 +856,17 @@ export class JaakStamps {
668
856
  }, 2000);
669
857
  }
670
858
  }
859
+ else if (!qualityCheckPassed) {
860
+ // Reset alignment timer if quality check fails
861
+ this.logger.state('QUALITY_CHECK_FAILED', {
862
+ enableQualityValidation: this.enableQualityValidation,
863
+ canCapture: this.qualityFeedback.canCapture,
864
+ qualityScore: this.qualityFeedback.score,
865
+ hasIssues: this.qualityFeedback.hasIssues
866
+ });
867
+ this.alignmentStartTime = undefined;
868
+ cardOutline?.classList.add('quality-warning');
869
+ }
671
870
  }
672
871
  else {
673
872
  cardOutline?.classList.remove('perfect-match');
@@ -843,7 +1042,12 @@ export class JaakStamps {
843
1042
  }
844
1043
  }
845
1044
  resetDetection() {
1045
+ const currentCaptureState = this.stateManager.getCaptureState();
1046
+ const wasVideoActive = currentCaptureState.isVideoActive;
846
1047
  this.stateManager.reset();
1048
+ if (wasVideoActive) {
1049
+ this.stateManager.updateCaptureState({ isVideoActive: true });
1050
+ }
847
1051
  this.hasScreenshotTaken = false;
848
1052
  this.startTime = Date.now();
849
1053
  this.frameSkipCounter = 0;
@@ -851,12 +1055,12 @@ export class JaakStamps {
851
1055
  this.lastInferenceTime = 0;
852
1056
  this.detectionBoxes = [];
853
1057
  this.alignmentStartTime = undefined;
1058
+ this.hasDocumentDetected = false;
854
1059
  if (this.alignmentTimer) {
855
1060
  clearTimeout(this.alignmentTimer);
856
1061
  this.alignmentTimer = undefined;
857
1062
  }
858
- const captureState = this.stateManager.getCaptureState();
859
- if (captureState.isVideoActive && this.detectionService.isModelLoaded()) {
1063
+ if (wasVideoActive && this.detectionService.isModelLoaded()) {
860
1064
  this.updateStatus('Captura reiniciada', 'Buscando documento en el marco de captura', 'active');
861
1065
  this.detectFrame();
862
1066
  }
@@ -870,6 +1074,7 @@ export class JaakStamps {
870
1074
  this.videoStream = undefined;
871
1075
  this.stateManager.updateCaptureState({ isVideoActive: false, isLoading: false });
872
1076
  }
1077
+ this.isMaskReady = false;
873
1078
  this.updateStatus('Sesión finalizada', '', 'ready');
874
1079
  this.detectionBoxes = [];
875
1080
  this.cleanup();
@@ -1058,6 +1263,146 @@ export class JaakStamps {
1058
1263
  "setter": false,
1059
1264
  "reflect": false,
1060
1265
  "defaultValue": "'auto'"
1266
+ },
1267
+ "captureDelay": {
1268
+ "type": "number",
1269
+ "attribute": "capture-delay",
1270
+ "mutable": false,
1271
+ "complexType": {
1272
+ "original": "number",
1273
+ "resolved": "number",
1274
+ "references": {}
1275
+ },
1276
+ "required": false,
1277
+ "optional": false,
1278
+ "docs": {
1279
+ "tags": [],
1280
+ "text": ""
1281
+ },
1282
+ "getter": false,
1283
+ "setter": false,
1284
+ "reflect": false,
1285
+ "defaultValue": "1000"
1286
+ },
1287
+ "enableQualityValidation": {
1288
+ "type": "boolean",
1289
+ "attribute": "enable-quality-validation",
1290
+ "mutable": false,
1291
+ "complexType": {
1292
+ "original": "boolean",
1293
+ "resolved": "boolean",
1294
+ "references": {}
1295
+ },
1296
+ "required": false,
1297
+ "optional": false,
1298
+ "docs": {
1299
+ "tags": [],
1300
+ "text": ""
1301
+ },
1302
+ "getter": false,
1303
+ "setter": false,
1304
+ "reflect": false,
1305
+ "defaultValue": "true"
1306
+ },
1307
+ "qualityThreshold": {
1308
+ "type": "number",
1309
+ "attribute": "quality-threshold",
1310
+ "mutable": false,
1311
+ "complexType": {
1312
+ "original": "number",
1313
+ "resolved": "number",
1314
+ "references": {}
1315
+ },
1316
+ "required": false,
1317
+ "optional": false,
1318
+ "docs": {
1319
+ "tags": [],
1320
+ "text": ""
1321
+ },
1322
+ "getter": false,
1323
+ "setter": false,
1324
+ "reflect": false,
1325
+ "defaultValue": "60"
1326
+ },
1327
+ "minQualityScore": {
1328
+ "type": "number",
1329
+ "attribute": "min-quality-score",
1330
+ "mutable": false,
1331
+ "complexType": {
1332
+ "original": "number",
1333
+ "resolved": "number",
1334
+ "references": {}
1335
+ },
1336
+ "required": false,
1337
+ "optional": false,
1338
+ "docs": {
1339
+ "tags": [],
1340
+ "text": ""
1341
+ },
1342
+ "getter": false,
1343
+ "setter": false,
1344
+ "reflect": false,
1345
+ "defaultValue": "45"
1346
+ },
1347
+ "minFocusScore": {
1348
+ "type": "number",
1349
+ "attribute": "min-focus-score",
1350
+ "mutable": false,
1351
+ "complexType": {
1352
+ "original": "number",
1353
+ "resolved": "number",
1354
+ "references": {}
1355
+ },
1356
+ "required": false,
1357
+ "optional": false,
1358
+ "docs": {
1359
+ "tags": [],
1360
+ "text": ""
1361
+ },
1362
+ "getter": false,
1363
+ "setter": false,
1364
+ "reflect": false,
1365
+ "defaultValue": "16"
1366
+ },
1367
+ "minBlurScore": {
1368
+ "type": "number",
1369
+ "attribute": "min-blur-score",
1370
+ "mutable": false,
1371
+ "complexType": {
1372
+ "original": "number",
1373
+ "resolved": "number",
1374
+ "references": {}
1375
+ },
1376
+ "required": false,
1377
+ "optional": false,
1378
+ "docs": {
1379
+ "tags": [],
1380
+ "text": ""
1381
+ },
1382
+ "getter": false,
1383
+ "setter": false,
1384
+ "reflect": false,
1385
+ "defaultValue": "22"
1386
+ },
1387
+ "maxReflectionScore": {
1388
+ "type": "number",
1389
+ "attribute": "max-reflection-score",
1390
+ "mutable": false,
1391
+ "complexType": {
1392
+ "original": "number",
1393
+ "resolved": "number",
1394
+ "references": {}
1395
+ },
1396
+ "required": false,
1397
+ "optional": false,
1398
+ "docs": {
1399
+ "tags": [],
1400
+ "text": ""
1401
+ },
1402
+ "getter": false,
1403
+ "setter": false,
1404
+ "reflect": false,
1405
+ "defaultValue": "15"
1061
1406
  }
1062
1407
  };
1063
1408
  }
@@ -1069,7 +1414,9 @@ export class JaakStamps {
1069
1414
  "shouldMirrorVideo": {},
1070
1415
  "showCameraSelector": {},
1071
1416
  "isSwitchingCamera": {},
1417
+ "hasDocumentDetected": {},
1072
1418
  "currentStatus": {},
1419
+ "qualityFeedback": {},
1073
1420
  "performanceData": {}
1074
1421
  };
1075
1422
  }
@@ -1281,6 +1628,150 @@ export class JaakStamps {
1281
1628
  "text": "",
1282
1629
  "tags": []
1283
1630
  }
1631
+ },
1632
+ "setCaptureDelay": {
1633
+ "complexType": {
1634
+ "signature": "(delay: number) => Promise<{ success: boolean; captureDelay: number; }>",
1635
+ "parameters": [{
1636
+ "name": "delay",
1637
+ "type": "number",
1638
+ "docs": ""
1639
+ }],
1640
+ "references": {
1641
+ "Promise": {
1642
+ "location": "global",
1643
+ "id": "global::Promise"
1644
+ }
1645
+ },
1646
+ "return": "Promise<{ success: boolean; captureDelay: number; }>"
1647
+ },
1648
+ "docs": {
1649
+ "text": "",
1650
+ "tags": []
1651
+ }
1652
+ },
1653
+ "getCaptureDelay": {
1654
+ "complexType": {
1655
+ "signature": "() => Promise<number>",
1656
+ "parameters": [],
1657
+ "references": {
1658
+ "Promise": {
1659
+ "location": "global",
1660
+ "id": "global::Promise"
1661
+ }
1662
+ },
1663
+ "return": "Promise<number>"
1664
+ },
1665
+ "docs": {
1666
+ "text": "",
1667
+ "tags": []
1668
+ }
1669
+ },
1670
+ "setTorchEnabled": {
1671
+ "complexType": {
1672
+ "signature": "(enabled: boolean) => Promise<{ success: boolean; enabled: boolean; }>",
1673
+ "parameters": [{
1674
+ "name": "enabled",
1675
+ "type": "boolean",
1676
+ "docs": ""
1677
+ }],
1678
+ "references": {
1679
+ "Promise": {
1680
+ "location": "global",
1681
+ "id": "global::Promise"
1682
+ }
1683
+ },
1684
+ "return": "Promise<{ success: boolean; enabled: boolean; }>"
1685
+ },
1686
+ "docs": {
1687
+ "text": "",
1688
+ "tags": []
1689
+ }
1690
+ },
1691
+ "focusAtPoint": {
1692
+ "complexType": {
1693
+ "signature": "(x: number, y: number) => Promise<{ success: boolean; coordinates: { x: number; y: number; }; }>",
1694
+ "parameters": [{
1695
+ "name": "x",
1696
+ "type": "number",
1697
+ "docs": ""
1698
+ }, {
1699
+ "name": "y",
1700
+ "type": "number",
1701
+ "docs": ""
1702
+ }],
1703
+ "references": {
1704
+ "Promise": {
1705
+ "location": "global",
1706
+ "id": "global::Promise"
1707
+ }
1708
+ },
1709
+ "return": "Promise<{ success: boolean; coordinates: { x: number; y: number; }; }>"
1710
+ },
1711
+ "docs": {
1712
+ "text": "",
1713
+ "tags": []
1714
+ }
1715
+ },
1716
+ "getImageQuality": {
1717
+ "complexType": {
1718
+ "signature": "() => Promise<{ qualityScore: any; overallQuality: any; issues: any; recommendations: any; canCapture: boolean; }>",
1719
+ "parameters": [],
1720
+ "references": {
1721
+ "Promise": {
1722
+ "location": "global",
1723
+ "id": "global::Promise"
1724
+ }
1725
+ },
1726
+ "return": "Promise<{ qualityScore: any; overallQuality: any; issues: any; recommendations: any; canCapture: boolean; }>"
1727
+ },
1728
+ "docs": {
1729
+ "text": "",
1730
+ "tags": []
1731
+ }
1732
+ },
1733
+ "setQualityThresholds": {
1734
+ "complexType": {
1735
+ "signature": "(thresholds: QualityThresholds) => Promise<{ success: boolean; thresholds: QualityThresholds; }>",
1736
+ "parameters": [{
1737
+ "name": "thresholds",
1738
+ "type": "QualityThresholds",
1739
+ "docs": ""
1740
+ }],
1741
+ "references": {
1742
+ "Promise": {
1743
+ "location": "global",
1744
+ "id": "global::Promise"
1745
+ },
1746
+ "QualityThresholds": {
1747
+ "location": "import",
1748
+ "path": "../../services/interfaces/IDetectionService",
1749
+ "id": "src/services/interfaces/IDetectionService.ts::QualityThresholds"
1750
+ }
1751
+ },
1752
+ "return": "Promise<{ success: boolean; thresholds: QualityThresholds; }>"
1753
+ },
1754
+ "docs": {
1755
+ "text": "",
1756
+ "tags": []
1757
+ }
1758
+ },
1759
+ "getQualityThresholds": {
1760
+ "complexType": {
1761
+ "signature": "() => Promise<{ minQualityScore: number; minFocusScore: number; minBlurScore: number; maxReflectionScore: number; }>",
1762
+ "parameters": [],
1763
+ "references": {
1764
+ "Promise": {
1765
+ "location": "global",
1766
+ "id": "global::Promise"
1767
+ }
1768
+ },
1769
+ "return": "Promise<{ minQualityScore: number; minFocusScore: number; minBlurScore: number; maxReflectionScore: number; }>"
1770
+ },
1771
+ "docs": {
1772
+ "text": "",
1773
+ "tags": []
1774
+ }
1284
1775
  }
1285
1776
  };
1286
1777
  }