use crate::model::{ContextItem, ScoredItem};
use crate::placer::Placer;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub struct UShapedPlacer;
impl Placer for UShapedPlacer {
fn place(&self, items: &[ScoredItem]) -> Vec<ContextItem> {
if items.is_empty() {
return Vec::new();
}
if items.len() == 1 {
return vec![items[0].item.clone()];
}
let mut scored: Vec<(f64, usize)> = items
.iter()
.enumerate()
.map(|(i, si)| (si.score, i))
.collect();
scored.sort_by(|a, b| b.0.total_cmp(&a.0).then_with(|| a.1.cmp(&b.1)));
let mut left: Vec<ContextItem> = Vec::new();
let mut right: Vec<ContextItem> = Vec::new();
for (rank, &(_, orig_idx)) in scored.iter().enumerate() {
let item = items[orig_idx].item.clone();
if rank % 2 == 0 {
left.push(item);
} else {
right.push(item);
}
}
right.reverse();
left.into_iter().chain(right).collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::model::ContextItemBuilder;
fn make_item(content: &str, score: f64) -> ScoredItem {
ScoredItem {
item: ContextItemBuilder::new(content, 5).build().unwrap(),
score,
}
}
#[test]
fn place_zero_items() {
let result = UShapedPlacer.place(&[]);
assert!(result.is_empty());
}
#[test]
fn place_one_item() {
let items = vec![make_item("A", 0.9)];
let result = UShapedPlacer.place(&items);
assert_eq!(result.len(), 1);
assert_eq!(result[0].content(), "A");
}
#[test]
fn place_two_items() {
let items = vec![make_item("A", 0.9), make_item("B", 0.1)];
let result = UShapedPlacer.place(&items);
assert_eq!(result.len(), 2);
assert_eq!(result[0].content(), "A"); assert_eq!(result[1].content(), "B"); }
#[test]
fn place_three_items() {
let items = vec![
make_item("A", 0.9),
make_item("B", 0.5),
make_item("C", 0.1),
];
let result = UShapedPlacer.place(&items);
assert_eq!(result.len(), 3);
assert_eq!(result[0].content(), "A"); assert_eq!(result[1].content(), "C"); assert_eq!(result[2].content(), "B"); }
#[test]
fn place_four_items() {
let items = vec![
make_item("A", 0.9),
make_item("B", 0.7),
make_item("C", 0.5),
make_item("D", 0.1),
];
let result = UShapedPlacer.place(&items);
assert_eq!(result.len(), 4);
assert_eq!(result[0].content(), "A"); assert_eq!(result[3].content(), "B"); }
}