use crate::float::Float;
use crate::value::NormalizedContainer;
use core::marker::PhantomData;
pub struct FixedScoreSet<T: Float, Members> {
pub(crate) members: Members,
_phantom: PhantomData<T>,
}
impl<T: Float, Members> FixedScoreSet<T, Members>
where
Members: crate::Members<T>,
{
#[doc(hidden)]
pub fn normalize(raw: Members::Raw) -> Result<Self, &'static str> {
let raw_weights = Members::extract_raw_weights(&raw);
let sum: T = raw_weights.iter().fold(T::zero(), |a, &b| a + b);
let normalized: Vec<T> = raw_weights.iter().map(|&w| w / sum).collect();
let mut sorted = normalized.clone();
sorted.sort_by(|a, b| a.partial_cmp(b).unwrap_or(core::cmp::Ordering::Equal));
let container = NormalizedContainer::witness(sorted)?;
Ok(FixedScoreSet {
members: Members::from_raw_with_weights(raw, &normalized, &container),
_phantom: PhantomData,
})
}
#[inline]
pub fn score(&self) -> FixedScoreStage<'_, T, Members> {
FixedScoreStage {
members: &self.members,
_phantom: PhantomData,
}
}
}
pub struct FixedScoreStage<'a, T: Float, Members> {
members: &'a Members,
_phantom: PhantomData<T>,
}
impl<'a, T: Float, Members> FixedScoreStage<'a, T, Members> {
#[inline]
pub fn by<F, R>(self, f: F) -> R
where
F: FnOnce(&Members) -> R,
{
f(self.members)
}
}
#[cfg(test)]
mod tests_for_fixed;