use std::collections::HashMap;
use std::hash::Hash;
use khive_score::DeterministicScore;
use super::config::HybridConfig;
use super::searcher::fuse_search_results;
pub fn fuse_labelled_scored<Id, L, F>(
arms: Vec<Vec<(Id, DeterministicScore, L)>>,
config: &HybridConfig,
combine: F,
) -> Vec<(Id, DeterministicScore, L)>
where
Id: Eq + Hash + Clone + Ord,
L: Clone,
F: Fn(L, L) -> L,
{
let mut scored_arms = Vec::with_capacity(arms.len());
for arm in &arms {
let mut scored = Vec::with_capacity(arm.len());
for (id, score, _) in arm {
scored.push((id.clone(), *score));
}
scored_arms.push(scored);
}
let ranked = fuse_search_results(scored_arms, config);
let mut labels: HashMap<Id, L> = HashMap::new();
for (id, _, label) in arms.into_iter().flatten() {
let merged = match labels.remove(&id) {
Some(held) => combine(held, label),
None => label,
};
labels.insert(id, merged);
}
ranked
.into_iter()
.map(|(id, score)| {
let label = labels.get(&id).expect("every scored id has a label");
(id, score, label.clone())
})
.collect()
}