use crate::codes::REGION_CODES;
use crate::ic::{compute_verify_code, IdentityCard};
use rand::{
prelude::{IteratorRandom, SliceRandom},
thread_rng, Rng,
};
const MAX_MONTHS: u16 = 12;
const LEAP_YEAR: [u16; 12] = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
const NORMAL_YEAR: [u16; 12] = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
fn is_leap(year: u16) -> bool {
year % 4 == 0
}
fn get_max_days(year: u16, month: u16) -> u16 {
if is_leap(year) {
return LEAP_YEAR[month as usize - 1];
} else {
return NORMAL_YEAR[month as usize - 1];
}
}
pub fn generate_identitycard(loc: String, birthday: String) -> IdentityCard {
let mut rng = thread_rng();
let region_code: String;
if loc.len() > 0 && loc.len() <= 6 {
region_code = REGION_CODES
.iter()
.filter(|x| x.starts_with(&loc))
.into_iter()
.choose(&mut rng)
.unwrap()
.to_string();
} else {
region_code = REGION_CODES.choose(&mut rng).unwrap().to_string()
}
let mut year = 0 as u16;
let mut month = 0 as u16;
let mut day = 0 as u16;
if birthday.len() == 4 {
year = birthday.parse::<u16>().unwrap();
month = rng.gen_range(1, MAX_MONTHS);
day = rng.gen_range(1, get_max_days(year, month));
} else if birthday.len() == 6 {
year = birthday[..4].parse::<u16>().unwrap();
month = birthday[4..].parse::<u16>().unwrap();
day = rng.gen_range(1, get_max_days(year, month));
} else if birthday.len() == 8 {
year = birthday[..4].parse::<u16>().unwrap();
month = birthday[4..6].parse::<u16>().unwrap();
day = birthday[6..].parse::<u16>().unwrap();
} else {
year = rng.gen_range(1990, 1999);
month = rng.gen_range(1, MAX_MONTHS);
day = rng.gen_range(1, get_max_days(year, month));
}
let birthday_code = format!("{y:>04}{m:>02}{d:>02}", y = year, m = month, d = day);
let seq_code = format!("{}", rng.gen_range(100, 999));
let verify_code = compute_verify_code(®ion_code, &birthday_code, &seq_code).to_string();
let ic = IdentityCard {
region: region_code,
birthday: birthday_code,
seq: seq_code,
verify: verify_code,
};
ic
}