use serde::{Deserialize, Serialize};
use crate::{
validate_pose, FrameAnalysis, LivenessChallenge, PoseCheck, VerificationThresholds,
FRAMES_OK_TO_CAPTURE,
};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum SessionDecision {
Waiting { check: PoseCheck, valid_frames: u8 },
CaptureReady { check: PoseCheck },
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VerificationSession {
challenge: LivenessChallenge,
thresholds: VerificationThresholds,
current_step: usize,
valid_frames: u8,
}
impl VerificationSession {
pub fn new(challenge: LivenessChallenge, thresholds: VerificationThresholds) -> Self {
Self {
challenge,
thresholds,
current_step: 0,
valid_frames: 0,
}
}
pub fn current_step(&self) -> usize {
self.current_step
}
pub fn advance_step(&mut self) {
self.current_step += 1;
self.valid_frames = 0;
}
pub fn tick(&mut self, frame: &FrameAnalysis, _timestamp_ms: u64) -> SessionDecision {
let check = self
.challenge
.steps
.get(self.current_step)
.map(|step| validate_pose(step, frame, &self.challenge, &self.thresholds))
.unwrap_or_else(|| PoseCheck::fail("No hay más pasos en el reto."));
if !check.valid {
self.valid_frames = 0;
return SessionDecision::Waiting {
check,
valid_frames: 0,
};
}
self.valid_frames = self.valid_frames.saturating_add(1);
if self.valid_frames >= FRAMES_OK_TO_CAPTURE {
self.valid_frames = 0;
SessionDecision::CaptureReady { check }
} else {
SessionDecision::Waiting {
check,
valid_frames: self.valid_frames,
}
}
}
}