1use bevy::prelude::*;
6
7use crate::prelude::Score;
8
9#[reflect_trait]
11pub trait Measure: std::fmt::Debug + Sync + Send {
12 fn calculate(&self, inputs: Vec<(&Score, f32)>) -> f32;
14}
15
16#[derive(Debug, Clone, Reflect)]
19pub struct WeightedSum;
20
21impl Measure for WeightedSum {
22 fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
23 scores
24 .iter()
25 .fold(0f32, |acc, (score, weight)| acc + score.0 * weight)
26 }
27}
28
29#[derive(Debug, Clone, Reflect)]
31pub struct WeightedProduct;
32
33impl Measure for WeightedProduct {
34 fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
35 scores
36 .iter()
37 .fold(0f32, |acc, (score, weight)| acc * score.0 * weight)
38 }
39}
40
41#[derive(Debug, Clone, Reflect)]
45pub struct ChebyshevDistance;
46
47impl Measure for ChebyshevDistance {
48 fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
49 scores
50 .iter()
51 .fold(0f32, |best, (score, weight)| (score.0 * weight).max(best))
52 }
53}
54
55#[derive(Debug, Clone, Default, Reflect)]
57pub struct WeightedMeasure;
58
59impl Measure for WeightedMeasure {
60 fn calculate(&self, scores: Vec<(&Score, f32)>) -> f32 {
61 let wsum: f32 = scores.iter().map(|(_score, weight)| weight).sum();
62
63 if wsum == 0.0 {
64 0.0
65 } else {
66 scores
67 .iter()
68 .map(|(score, weight)| weight / wsum * score.get().powf(2.0))
69 .sum::<f32>()
70 .powf(1.0 / 2.0)
71 }
72 }
73}