1use crate::affordance::CatalogEntry;
8use std::collections::HashMap;
9
10#[derive(Debug, Clone)]
13pub struct ScoredAffordance<P = String> {
14 pub entry: CatalogEntry<P>,
16 pub score: f64,
18 pub bindings: HashMap<String, String>,
20}
21
22pub trait AcceptanceEval<P = String> {
30 fn evaluate(&self, responder: &str, action: &ScoredAffordance<P>) -> bool;
32}
33
34pub trait ActionScorer<P = String> {
40 fn score_actions(
42 &self,
43 actor: &str,
44 available: &[CatalogEntry<P>],
45 participants: &[String],
46 ) -> Vec<ScoredAffordance<P>>;
47}
48
49pub struct AlwaysAccept;
51
52impl<P> AcceptanceEval<P> for AlwaysAccept {
53 fn evaluate(&self, _responder: &str, _action: &ScoredAffordance<P>) -> bool {
54 true
55 }
56}
57
58pub struct AlwaysReject;
60
61impl<P> AcceptanceEval<P> for AlwaysReject {
62 fn evaluate(&self, _responder: &str, _action: &ScoredAffordance<P>) -> bool {
63 false
64 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70 use crate::affordance::AffordanceSpec;
71
72 fn test_scored(name: &str, score: f64) -> ScoredAffordance<String> {
73 let spec = AffordanceSpec {
74 name: name.to_string(),
75 domain: "test".to_string(),
76 bindings: vec![],
77 considerations: vec![],
78 effects_on_accept: vec![],
79 effects_on_reject: vec![],
80 drive_alignment: vec![],
81 };
82 let entry = CatalogEntry {
83 spec,
84 precondition: String::new(),
85 };
86 ScoredAffordance {
87 entry,
88 score,
89 bindings: HashMap::new(),
90 }
91 }
92
93 #[test]
94 fn always_accept_accepts() {
95 let eval = AlwaysAccept;
96 let action = test_scored("greet", 0.9);
97 assert!(eval.evaluate("alice", &action));
98 }
99
100 #[test]
101 fn always_reject_rejects() {
102 let eval = AlwaysReject;
103 let action = test_scored("threaten", 0.5);
104 assert!(!eval.evaluate("bob", &action));
105 }
106
107 #[test]
108 fn always_accept_works_with_unit_precondition() {
109 let spec = AffordanceSpec {
110 name: "wave".to_string(),
111 domain: "social".to_string(),
112 bindings: vec![],
113 considerations: vec![],
114 effects_on_accept: vec![],
115 effects_on_reject: vec![],
116 drive_alignment: vec![],
117 };
118 let entry: CatalogEntry<()> = CatalogEntry {
119 spec,
120 precondition: (),
121 };
122 let action: ScoredAffordance<()> = ScoredAffordance {
123 entry,
124 score: 1.0,
125 bindings: HashMap::new(),
126 };
127 let eval = AlwaysAccept;
128 assert!(eval.evaluate("carol", &action));
129 }
130}