use serde::{Deserialize, Serialize};
use std::time::SystemTime;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct EmotionalState {
pub valence: f64,
pub arousal: f64,
pub curiosity: f64,
pub confidence: f64,
#[serde(skip)]
pub timestamp: Option<SystemTime>,
}
impl Default for EmotionalState {
fn default() -> Self {
Self {
valence: 0.0,
arousal: 0.5,
curiosity: 0.5,
confidence: 0.5,
timestamp: Some(SystemTime::now()),
}
}
}
impl EmotionalState {
pub fn neutral() -> Self {
Self::default()
}
pub fn positive() -> Self {
Self {
valence: 0.7,
arousal: 0.6,
curiosity: 0.7,
confidence: 0.8,
timestamp: Some(SystemTime::now()),
}
}
pub fn blend(&self, other: &EmotionalState, weight: f64) -> EmotionalState {
let w = weight.clamp(0.0, 1.0);
let w_inv = 1.0 - w;
EmotionalState {
valence: self.valence * w_inv + other.valence * w,
arousal: self.arousal * w_inv + other.arousal * w,
curiosity: self.curiosity * w_inv + other.curiosity * w,
confidence: self.confidence * w_inv + other.confidence * w,
timestamp: Some(SystemTime::now()),
}
}
pub fn is_positive(&self) -> bool {
self.valence > 0.2
}
pub fn is_engaged(&self) -> bool {
(self.curiosity + self.arousal) / 2.0 > 0.6
}
}
#[derive(Debug, Clone)]
pub struct EmotionalHistory {
states: Vec<EmotionalState>,
max_size: usize,
}
impl EmotionalHistory {
pub fn new(max_size: usize) -> Self {
Self {
states: Vec::new(),
max_size,
}
}
pub fn record(&mut self, state: EmotionalState) {
self.states.push(state);
if self.states.len() > self.max_size {
self.states.remove(0);
}
}
pub fn valence_trend(&self) -> f64 {
if self.states.len() < 2 {
return 0.0;
}
let recent_n = self.states.len().min(5);
let recent_avg: f64 = self.states[self.states.len() - recent_n..]
.iter()
.map(|s| s.valence)
.sum::<f64>()
/ recent_n as f64;
let earlier_avg: f64 = self.states[..self.states.len() - recent_n]
.iter()
.map(|s| s.valence)
.sum::<f64>()
/ (self.states.len() - recent_n) as f64;
recent_avg - earlier_avg
}
pub fn current(&self) -> Option<&EmotionalState> {
self.states.last()
}
}