use bevy::prelude::*;
use crate::{choices::Choice, scorers::Score};
#[reflect_trait]
pub trait Picker: std::fmt::Debug + Sync + Send {
fn pick<'a>(&self, choices: &'a [Choice], scores: &Query<&Score>) -> Option<&'a Choice>;
}
#[derive(Debug, Clone, Default)]
pub struct FirstToScore {
pub threshold: f32,
}
impl FirstToScore {
pub fn new(threshold: f32) -> Self {
Self { threshold }
}
}
impl Picker for FirstToScore {
fn pick<'a>(&self, choices: &'a [Choice], scores: &Query<&Score>) -> Option<&'a Choice> {
for choice in choices {
let value = choice.calculate(scores);
if value >= self.threshold {
return Some(choice);
}
}
None
}
}
#[derive(Debug, Clone, Default)]
pub struct Highest;
impl Picker for Highest {
fn pick<'a>(&self, choices: &'a [Choice], scores: &Query<&Score>) -> Option<&'a Choice> {
let mut max_score = 0f32;
choices.iter().fold(None, |acc, choice| {
let score = choice.calculate(scores);
if score <= max_score || score <= 0.0 {
return acc;
}
max_score = score;
Some(choice)
})
}
}
#[derive(Debug, Clone, Default)]
pub struct HighestToScore {
pub threshold: f32,
}
impl HighestToScore {
pub fn new(threshold: f32) -> Self {
Self { threshold }
}
}
impl Picker for HighestToScore {
fn pick<'a>(&self, choices: &'a [Choice], scores: &Query<&Score>) -> Option<&'a Choice> {
let mut highest_score = 0f32;
choices.iter().fold(None, |acc, choice| {
let score = choice.calculate(scores);
if score <= self.threshold || score <= highest_score {
return acc;
}
highest_score = score;
Some(choice)
})
}
}