use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct EmotionalState {
pub joy: f32,
pub trust: f32,
pub fear: f32,
pub surprise: f32,
pub sadness: f32,
pub disgust: f32,
pub anger: f32,
pub anticipation: f32,
decay_rate: f32,
}
impl EmotionalState {
pub fn new() -> Self {
Self {
joy: 0.0,
trust: 0.0,
fear: 0.0,
surprise: 0.0,
sadness: 0.0,
disgust: 0.0,
anger: 0.0,
anticipation: 0.0,
decay_rate: 0.1, }
}
pub fn with_decay_rate(decay_rate: f32) -> Self {
let mut state = Self::new();
state.decay_rate = decay_rate.clamp(0.0, 1.0);
state
}
pub fn valence(&self) -> f32 {
let positive = self.joy + self.trust + self.anticipation;
let negative = self.sadness + self.disgust + self.anger + self.fear;
((positive - negative) / 7.0).clamp(-1.0, 1.0)
}
pub fn arousal(&self) -> f32 {
let total = self.joy.abs()
+ self.trust.abs()
+ self.fear.abs()
+ self.surprise.abs()
+ self.sadness.abs()
+ self.disgust.abs()
+ self.anger.abs()
+ self.anticipation.abs();
(total / 8.0).clamp(0.0, 1.0)
}
pub fn dominant_emotion(&self) -> (&'static str, f32) {
let emotions = [
("joy", self.joy),
("trust", self.trust),
("fear", self.fear),
("surprise", self.surprise),
("sadness", self.sadness),
("disgust", self.disgust),
("anger", self.anger),
("anticipation", self.anticipation),
];
emotions
.iter()
.max_by(|(_, a), (_, b)| a.abs().partial_cmp(&b.abs()).unwrap())
.map(|(name, value)| (*name, *value))
.unwrap_or(("neutral", 0.0))
}
pub fn decay(&mut self) {
self.joy *= 1.0 - self.decay_rate;
self.trust *= 1.0 - self.decay_rate;
self.fear *= 1.0 - self.decay_rate;
self.surprise *= 1.0 - self.decay_rate;
self.sadness *= 1.0 - self.decay_rate;
self.disgust *= 1.0 - self.decay_rate;
self.anger *= 1.0 - self.decay_rate;
self.anticipation *= 1.0 - self.decay_rate;
}
pub fn update_emotion(&mut self, emotion: &str, delta: f32) {
let value = match emotion {
"joy" => &mut self.joy,
"trust" => &mut self.trust,
"fear" => &mut self.fear,
"surprise" => &mut self.surprise,
"sadness" => &mut self.sadness,
"disgust" => &mut self.disgust,
"anger" => &mut self.anger,
"anticipation" => &mut self.anticipation,
_ => return,
};
*value = (*value + delta).clamp(-1.0, 1.0);
match emotion {
"joy" => self.sadness = -self.joy,
"sadness" => self.joy = -self.sadness,
"trust" => self.disgust = -self.trust,
"disgust" => self.trust = -self.disgust,
"fear" => self.anger = -self.fear,
"anger" => self.fear = -self.anger,
"surprise" => self.anticipation = -self.surprise,
"anticipation" => self.surprise = -self.anticipation,
_ => {}
}
}
pub fn set_emotions(&mut self, emotions: Vec<(&str, f32)>) {
for (emotion, value) in emotions {
self.update_emotion(emotion, value);
}
}
pub fn is_positive(&self) -> bool {
self.valence() > 0.2
}
pub fn is_negative(&self) -> bool {
self.valence() < -0.2
}
pub fn is_aroused(&self) -> bool {
self.arousal() > 0.5
}
pub fn reset(&mut self) {
self.joy = 0.0;
self.trust = 0.0;
self.fear = 0.0;
self.surprise = 0.0;
self.sadness = 0.0;
self.disgust = 0.0;
self.anger = 0.0;
self.anticipation = 0.0;
}
pub fn as_vector(&self) -> [f32; 8] {
[
self.joy,
self.trust,
self.fear,
self.surprise,
self.sadness,
self.disgust,
self.anger,
self.anticipation,
]
}
}
impl Default for EmotionalState {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_emotional_state() {
let state = EmotionalState::new();
assert_eq!(state.joy, 0.0);
assert_eq!(state.trust, 0.0);
assert_eq!(state.fear, 0.0);
assert_eq!(state.valence(), 0.0);
assert_eq!(state.arousal(), 0.0);
}
#[test]
fn test_valence_calculation() {
let mut state = EmotionalState::new();
state.joy = 0.8;
state.trust = 0.6;
state.sadness = 0.0;
state.disgust = 0.0;
state.anger = 0.0;
state.fear = 0.0;
assert!(state.valence() > 0.0);
assert!(state.is_positive());
state.joy = 0.0;
state.trust = 0.0;
state.sadness = 0.9;
state.anger = 0.7;
assert!(state.valence() < 0.0);
assert!(state.is_negative());
}
#[test]
fn test_arousal_calculation() {
let mut state = EmotionalState::new();
state.joy = 0.9;
state.fear = 0.8;
state.anger = 0.7;
state.surprise = 0.8;
state.trust = 0.9;
assert!(state.arousal() > 0.0);
assert!(state.is_aroused());
}
#[test]
fn test_dominant_emotion() {
let mut state = EmotionalState::new();
state.joy = 0.9;
state.fear = 0.3;
let (emotion, value) = state.dominant_emotion();
assert_eq!(emotion, "joy");
assert_eq!(value, 0.9);
}
#[test]
fn test_emotion_decay() {
let mut state = EmotionalState::with_decay_rate(0.5);
state.joy = 1.0;
state.decay();
assert_eq!(state.joy, 0.5);
state.decay();
assert_eq!(state.joy, 0.25);
}
#[test]
fn test_update_emotion() {
let mut state = EmotionalState::new();
state.update_emotion("joy", 0.5);
assert_eq!(state.joy, 0.5);
assert_eq!(state.sadness, -0.5);
state.update_emotion("joy", 0.8);
assert_eq!(state.joy, 1.0); }
#[test]
fn test_set_emotions() {
let mut state = EmotionalState::new();
state.set_emotions(vec![("joy", 0.7), ("trust", 0.5), ("fear", 0.3)]);
assert_eq!(state.joy, 0.7);
assert_eq!(state.trust, 0.5);
assert_eq!(state.fear, 0.3);
}
#[test]
fn test_reset() {
let mut state = EmotionalState::new();
state.set_emotions(vec![("joy", 0.7), ("anger", 0.5)]);
state.reset();
assert_eq!(state.joy, 0.0);
assert_eq!(state.anger, 0.0);
assert_eq!(state.valence(), 0.0);
}
}