use rand::Rng;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ChallengeStep {
FaceCentered,
Smile,
TurnLeftOnScreen,
TurnRightOnScreen,
ShowFingers { count: u8 },
TouchTarget { target: TouchTarget },
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum TouchTarget {
Nose,
Cheek,
Ear,
}
impl TouchTarget {
fn random(rng: &mut impl Rng) -> Self {
match rng.gen_range(0..3) {
0 => Self::Nose,
1 => Self::Cheek,
_ => Self::Ear,
}
}
pub(crate) fn touch_message(self) -> &'static str {
match self {
TouchTarget::Nose => "Acerca el dedo a la nariz.",
TouchTarget::Cheek => "Acerca el dedo a la mejilla.",
TouchTarget::Ear => "Acerca el dedo a la oreja.",
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct LivenessChallenge {
pub steps: Vec<ChallengeStep>,
}
impl LivenessChallenge {
pub fn six_step(count: u8, target: TouchTarget) -> Self {
Self {
steps: vec![
ChallengeStep::FaceCentered,
ChallengeStep::Smile,
ChallengeStep::TurnLeftOnScreen,
ChallengeStep::TurnRightOnScreen,
ChallengeStep::ShowFingers { count },
ChallengeStep::TouchTarget { target },
],
}
}
pub fn random(rng: &mut impl Rng) -> Self {
let first_left = rng.gen_bool(0.5);
let fingers = rng.gen_range(1..=5);
let target = TouchTarget::random(rng);
let first = if first_left {
ChallengeStep::TurnLeftOnScreen
} else {
ChallengeStep::TurnRightOnScreen
};
let second = if first_left {
ChallengeStep::TurnRightOnScreen
} else {
ChallengeStep::TurnLeftOnScreen
};
Self {
steps: vec![
ChallengeStep::FaceCentered,
ChallengeStep::Smile,
first,
second,
ChallengeStep::ShowFingers { count: fingers },
ChallengeStep::TouchTarget { target },
],
}
}
}