/// Reciprocal Rank Fusion score for rank position i (0-based), k=60 standard.
pub fn rrf_score(rank: usize, k: usize) -> f64 {
    1.0 / (k + rank + 1) as f64
}

/// Fuse multiple rank lists into a single score map.
pub fn fuse(rank_lists: &[Vec<String>]) -> Vec<(String, f64)> {
    let mut scores: std::collections::HashMap<String, f64> = std::collections::HashMap::new();
    for list in rank_lists {
        for (rank, id) in list.iter().enumerate() {
            *scores.entry(id.clone()).or_default() += rrf_score(rank, 60);
        }
    }
    let mut result: Vec<(String, f64)> = scores.into_iter().collect();
    result.sort_by(|a, b| b.1.partial_cmp(&a.1).unwrap());
    result
}
