use std::f64; use crate::fitter::Recursive; use crate::item::Item; use crate::kernel::Kernel; use crate::observation::*; use crate::storage::Storage; #[derive(Clone, Copy)] pub enum DifferenceModelFitMethod { Ep, Kl, } pub struct DifferenceModel { storage: Storage, last_t: f64, observations: Vec, _last_method: Option, var: f64, } impl DifferenceModel { pub fn new(var: f64) -> Self { DifferenceModel { storage: Storage::default(), last_t: f64::NEG_INFINITY, observations: Vec::new(), _last_method: None, var, // default = 1.0 } } pub fn add_item(&mut self, name: &str, kernel: Box) { if self.storage.contains_key(name) { panic!("item '{}' already added", name); } self.storage.insert( name.to_string(), Item::new(Box::new(Recursive::new(kernel))), ); } pub fn contains_item(&self, name: &str) -> bool { self.storage.contains_key(name) } pub fn item_score(&self, name: &str, t: f64) -> (f64, f64) { let id = self.storage.get_id(name); let (ms, vs) = self.storage.item(id).fitter.predict(&[t]); (ms[0], vs[0]) } pub fn observe( &mut self, winners: &[&str], losers: &[&str], diff: f64, t: f64, var: Option, ) { if t < self.last_t { panic!("observations must be added in chronological order"); } let var = var.unwrap_or(self.var); let mut elems = self.process_items(winners, 1.0); elems.extend(self.process_items(losers, -1.0)); let obs = GaussianObservation::new(&mut self.storage, &elems, diff, t, var); self.observations.push(obs); self.last_t = t; } pub fn fit(&mut self) -> bool { unimplemented!(); } pub fn probabilities( &mut self, _team_1: &[&str], _team_2: &[&str], _t: f64, _margin: Option, ) -> (f64, f64, f64) { unimplemented!(); } fn process_items(&self, items: &[&str], sign: f64) -> Vec<(usize, f64)> { items .iter() .map(|key| (self.storage.get_id(key), sign)) .collect() } }