use crate::AnalyzedPassword;
#[cfg(feature = "common-password")]
#[inline]
fn is_common(analyzed_password: &AnalyzedPassword) -> bool {
analyzed_password.is_common()
}
#[cfg(not(feature = "common-password"))]
#[inline]
fn is_common(_: &AnalyzedPassword) -> bool {
false
}
pub fn score(analyzed_password: &AnalyzedPassword) -> f64 {
let max_score = match analyzed_password.length() - analyzed_password.other_characters_count() {
0 => 0f64,
1 => 2f64,
2 => 5f64,
3 => 9f64,
4 => 16f64,
5 => 25f64,
6 => 40f64,
7 => 58f64,
8 => 80f64,
9 => 88f64,
10 => 95f64,
11 => 100f64,
_ => (100 + analyzed_password.length() - 11) as f64,
};
let mut score = max_score;
if score > 0f64 {
if analyzed_password.spaces_count() >= 1 {
score += analyzed_password.spaces_count() as f64;
}
if analyzed_password.numbers_count() == 0 {
score -= max_score * 0.05;
}
if analyzed_password.lowercase_letters_count() == 0 {
score -= max_score * 0.1;
}
if analyzed_password.uppercase_letters_count() == 0 {
score -= max_score * 0.1;
}
if analyzed_password.spaces_count() == 0 {
score -= max_score * 0.1;
}
if analyzed_password.lowercase_letters_count() >= 1
&& analyzed_password.uppercase_letters_count() >= 1
{
score += 1f64;
}
if analyzed_password.symbols_count() >= 1 {
score += 1f64;
}
score -= max_score
* (analyzed_password.consecutive_count() as f64
/ analyzed_password.length() as f64
/ 5f64);
score -= max_score
* (analyzed_password.progressive_count() as f64
/ analyzed_password.length() as f64
/ 5f64);
score -= max_score
* (analyzed_password.non_consecutive_count() as f64
/ analyzed_password.length() as f64
/ 10f64);
}
score = score.clamp(0f64, max_score);
score += analyzed_password.other_characters_count() as f64 * 20f64;
if score > 100f64 {
score = 100f64;
}
if is_common(analyzed_password) {
score /= 5f64;
}
score
}