use crate::{Scalar, condition::*, score_mapping::*};
pub trait Consideration<M = ()>: Send + Sync {
fn score(&self, memory: &M) -> Scalar;
fn remap<T>(self, mapping: T) -> ConsiderationRemap<M, T>
where
T: ScoreMapping,
Self: Sized + 'static,
{
ConsiderationRemap::new(self, mapping)
}
}
impl<M> Consideration<M> for Scalar {
fn score(&self, _: &M) -> Scalar {
*self
}
}
pub struct ClosureConsideration<M = ()>(pub Box<dyn Fn(&M) -> Scalar + Send + Sync>);
impl<M> ClosureConsideration<M> {
pub fn new<F>(f: F) -> Self
where
F: Fn(&M) -> Scalar + 'static + Send + Sync,
{
Self(Box::new(f))
}
}
impl<M> Consideration<M> for ClosureConsideration<M> {
fn score(&self, memory: &M) -> Scalar {
(self.0)(memory)
}
}
impl<M> std::fmt::Debug for ClosureConsideration<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ClosureConsideration").finish()
}
}
pub struct ConsiderationRemap<M = (), T = NoScoreMapping>
where
T: ScoreMapping,
{
pub consideration: Box<dyn Consideration<M>>,
pub mapping: T,
}
impl<M, T> ConsiderationRemap<M, T>
where
T: ScoreMapping,
{
pub fn new<C>(consideration: C, mapping: T) -> Self
where
C: Consideration<M> + 'static,
{
Self {
consideration: Box::new(consideration),
mapping,
}
}
}
impl<M, T> Consideration<M> for ConsiderationRemap<M, T>
where
T: ScoreMapping,
{
fn score(&self, memory: &M) -> Scalar {
self.mapping.remap(self.consideration.score(memory))
}
}
impl<M, T> std::fmt::Debug for ConsiderationRemap<M, T>
where
T: ScoreMapping + std::fmt::Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ConsiderationRemap")
.field("mapping", &self.mapping)
.finish()
}
}
pub struct ConditionConsideration<M = ()> {
pub condition: Box<dyn Condition<M>>,
pub positive: Scalar,
pub negative: Scalar,
}
impl<M> ConditionConsideration<M> {
pub fn new<C>(condition: C, positive: Scalar, negative: Scalar) -> Self
where
C: Condition<M> + 'static,
{
Self {
condition: Box::new(condition),
positive,
negative,
}
}
pub fn unit<C>(condition: C) -> Self
where
C: Condition<M> + 'static,
{
Self {
condition: Box::new(condition),
positive: 1.0,
negative: 0.0,
}
}
}
impl<M> Consideration<M> for ConditionConsideration<M> {
fn score(&self, memory: &M) -> Scalar {
if self.condition.validate(memory) {
self.positive
} else {
self.negative
}
}
}
impl<M> std::fmt::Debug for ConditionConsideration<M> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("ConditionConsideration")
.field("positive", &self.positive)
.field("negative", &self.negative)
.finish()
}
}