pub mod jaro_winkler;
pub mod levenshtein;
pub mod normalize;
pub mod trigram;
pub use jaro_winkler::jaro_winkler;
pub use levenshtein::levenshtein;
pub use normalize::normalize;
pub use trigram::trigram_similarity;
pub fn combined_score(a: &str, b: &str) -> f64 {
let lev = levenshtein(a, b);
let max_len = a.chars().count().max(b.chars().count());
let lev_sim = if max_len == 0 {
1.0
} else {
1.0 - (lev as f64 / max_len as f64)
};
let jw = jaro_winkler(a, b);
let tri = trigram_similarity(a, b);
lev_sim * 0.35 + jw * 0.40 + tri * 0.25
}
pub fn best_match<'a>(query: &str, candidates: &[&'a str]) -> Option<(&'a str, f64)> {
candidates
.iter()
.map(|c| (*c, combined_score(query, c)))
.max_by(|a, b| a.1.partial_cmp(&b.1).unwrap())
}
pub fn rank_matches<'a>(query: &str, candidates: &[&'a str]) -> Vec<(&'a str, f64)> {
let mut results: Vec<(&str, f64)> = candidates
.iter()
.map(|c| (*c, combined_score(query, c)))
.collect();
results.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
results
}
pub mod python;