use std::{cmp::Ordering, sync::Arc, time::SystemTime};
use scion_proto::path::Path;
use crate::path::{
policy::PathPolicy,
scoring::{PathScorer, PathScoring},
types::PathManagerPath,
};
pub mod policy;
pub mod scoring;
#[derive(Default)]
pub struct PathStrategy {
pub policies: Vec<Arc<dyn PathPolicy>>,
pub scoring: PathScorer,
}
impl PathStrategy {
pub fn add_policy(&mut self, policy: impl PathPolicy) {
self.policies.push(Arc::new(policy));
}
pub fn add_scoring(&mut self, scoring: impl PathScoring, impact: f32) {
self.scoring = self.scoring.clone().with_scorer(scoring, impact);
}
pub fn rank_order(
&self,
this: &PathManagerPath,
other: &PathManagerPath,
now: SystemTime,
) -> Ordering {
let this_score = self.scoring.score(this, now);
let other_score = self.scoring.score(other, now);
this_score.total_cmp(&other_score).reverse() }
pub fn rank_inplace(&self, path: &mut [PathManagerPath], now: SystemTime) {
path.sort_by(|a, b| self.rank_order(a, b, now));
}
pub fn predicate(&self, path: &Path) -> bool {
self.policies.iter().all(|policy| policy.predicate(path))
}
pub fn filter_inplace<'path: 'iter, 'iter>(&self, paths: &mut Vec<Path>) {
paths.retain(|p| self.predicate(p));
}
}