use crate::state::StateValue;
use crate::types::Duration;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SocialCognition {
loneliness: StateValue,
perceived_reciprocal_caring: StateValue,
perceived_liability: StateValue,
self_hate: StateValue,
perceived_competence: StateValue,
}
impl SocialCognition {
pub(crate) const LONELINESS_DECAY_HALF_LIFE: Duration = Duration::days(1);
pub(crate) const PERCEIVED_RECIPROCAL_CARING_DECAY_HALF_LIFE: Duration = Duration::days(2);
pub(crate) const PERCEIVED_LIABILITY_DECAY_HALF_LIFE: Duration = Duration::days(3);
pub(crate) const SELF_HATE_DECAY_HALF_LIFE: Duration = Duration::days(3);
pub(crate) const PERCEIVED_COMPETENCE_DECAY_HALF_LIFE: Duration = Duration::days(7);
#[must_use]
pub fn new() -> Self {
SocialCognition {
loneliness: StateValue::new(0.2)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::LONELINESS_DECAY_HALF_LIFE),
perceived_reciprocal_caring: StateValue::new(0.6)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::PERCEIVED_RECIPROCAL_CARING_DECAY_HALF_LIFE),
perceived_liability: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::PERCEIVED_LIABILITY_DECAY_HALF_LIFE),
self_hate: StateValue::new(0.1)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::SELF_HATE_DECAY_HALF_LIFE),
perceived_competence: StateValue::new(0.5)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::PERCEIVED_COMPETENCE_DECAY_HALF_LIFE),
}
}
#[must_use]
pub fn with_loneliness_base(mut self, value: f32) -> Self {
self.loneliness.set_base(value);
self
}
#[must_use]
pub fn with_perceived_reciprocal_caring_base(mut self, value: f32) -> Self {
self.perceived_reciprocal_caring.set_base(value);
self
}
#[must_use]
pub fn with_perceived_liability_base(mut self, value: f32) -> Self {
self.perceived_liability.set_base(value);
self
}
#[must_use]
pub fn with_self_hate_base(mut self, value: f32) -> Self {
self.self_hate.set_base(value);
self
}
#[must_use]
pub fn with_perceived_competence_base(mut self, value: f32) -> Self {
self.perceived_competence.set_base(value);
self
}
#[must_use]
pub fn loneliness_effective(&self) -> f32 {
self.loneliness.effective()
}
#[must_use]
pub fn perceived_reciprocal_caring_effective(&self) -> f32 {
self.perceived_reciprocal_caring.effective()
}
#[must_use]
pub fn perceived_liability_effective(&self) -> f32 {
self.perceived_liability.effective()
}
#[must_use]
pub fn self_hate_effective(&self) -> f32 {
self.self_hate.effective()
}
#[must_use]
pub fn perceived_competence_effective(&self) -> f32 {
self.perceived_competence.effective()
}
#[must_use]
pub fn loneliness_base(&self) -> f32 {
self.loneliness.base()
}
#[must_use]
pub fn perceived_reciprocal_caring_base(&self) -> f32 {
self.perceived_reciprocal_caring.base()
}
#[must_use]
pub fn perceived_liability_base(&self) -> f32 {
self.perceived_liability.base()
}
#[must_use]
pub fn self_hate_base(&self) -> f32 {
self.self_hate.base()
}
#[must_use]
pub fn perceived_competence_base(&self) -> f32 {
self.perceived_competence.base()
}
#[must_use]
pub fn loneliness(&self) -> &StateValue {
&self.loneliness
}
#[must_use]
pub fn perceived_reciprocal_caring(&self) -> &StateValue {
&self.perceived_reciprocal_caring
}
#[must_use]
pub fn perceived_liability(&self) -> &StateValue {
&self.perceived_liability
}
#[must_use]
pub fn self_hate(&self) -> &StateValue {
&self.self_hate
}
#[must_use]
pub fn perceived_competence(&self) -> &StateValue {
&self.perceived_competence
}
pub fn loneliness_mut(&mut self) -> &mut StateValue {
&mut self.loneliness
}
pub fn perceived_reciprocal_caring_mut(&mut self) -> &mut StateValue {
&mut self.perceived_reciprocal_caring
}
pub fn perceived_liability_mut(&mut self) -> &mut StateValue {
&mut self.perceived_liability
}
pub fn self_hate_mut(&mut self) -> &mut StateValue {
&mut self.self_hate
}
pub fn perceived_competence_mut(&mut self) -> &mut StateValue {
&mut self.perceived_competence
}
pub fn add_loneliness_delta(&mut self, amount: f32) {
self.loneliness.add_delta(amount);
}
pub fn add_perceived_reciprocal_caring_delta(&mut self, amount: f32) {
self.perceived_reciprocal_caring.add_delta(amount);
}
pub fn add_perceived_liability_delta(&mut self, amount: f32) {
self.perceived_liability.add_delta(amount);
}
pub fn add_self_hate_delta(&mut self, amount: f32) {
self.self_hate.add_delta(amount);
}
pub fn add_perceived_competence_delta(&mut self, amount: f32) {
self.perceived_competence.add_delta(amount);
}
pub fn apply_decay(&mut self, elapsed: Duration) {
self.loneliness.apply_decay(elapsed);
self.perceived_reciprocal_caring.apply_decay(elapsed);
self.perceived_liability.apply_decay(elapsed);
self.self_hate.apply_decay(elapsed);
self.perceived_competence.apply_decay(elapsed);
}
pub fn reset_deltas(&mut self) {
self.loneliness.reset_delta();
self.perceived_reciprocal_caring.reset_delta();
self.perceived_liability.reset_delta();
self.self_hate.reset_delta();
self.perceived_competence.reset_delta();
}
}
impl Default for SocialCognition {
fn default() -> Self {
SocialCognition::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_default_values() {
let social = SocialCognition::new();
assert!((social.loneliness_effective() - 0.2).abs() < f32::EPSILON);
assert!((social.perceived_reciprocal_caring_effective() - 0.6).abs() < f32::EPSILON);
assert!((social.perceived_liability_effective() - 0.0).abs() < f32::EPSILON);
assert!((social.self_hate_effective() - 0.1).abs() < f32::EPSILON);
assert!((social.perceived_competence_effective() - 0.5).abs() < f32::EPSILON);
}
#[test]
fn builder_methods_set_bases() {
let social = SocialCognition::new()
.with_loneliness_base(0.4)
.with_perceived_reciprocal_caring_base(0.3)
.with_perceived_liability_base(0.2)
.with_self_hate_base(0.5)
.with_perceived_competence_base(0.7);
assert!((social.loneliness_base() - 0.4).abs() < f32::EPSILON);
assert!((social.perceived_reciprocal_caring_base() - 0.3).abs() < f32::EPSILON);
assert!((social.perceived_liability_base() - 0.2).abs() < f32::EPSILON);
assert!((social.self_hate_base() - 0.5).abs() < f32::EPSILON);
assert!((social.perceived_competence_base() - 0.7).abs() < f32::EPSILON);
}
#[test]
fn delta_methods_update_values() {
let mut social = SocialCognition::new();
social.add_loneliness_delta(0.2);
social.add_perceived_reciprocal_caring_delta(-0.1);
social.add_perceived_liability_delta(0.3);
social.add_self_hate_delta(0.4);
social.add_perceived_competence_delta(0.5);
assert!((social.loneliness().delta() - 0.2).abs() < f32::EPSILON);
assert!((social.perceived_reciprocal_caring().delta() - (-0.1)).abs() < f32::EPSILON);
assert!((social.perceived_liability().delta() - 0.3).abs() < f32::EPSILON);
assert!((social.self_hate().delta() - 0.4).abs() < f32::EPSILON);
assert!((social.perceived_competence().delta() - 0.5).abs() < f32::EPSILON);
}
#[test]
fn mutable_references_work() {
let mut social = SocialCognition::new();
social.loneliness_mut().add_delta(0.1);
social.perceived_reciprocal_caring_mut().add_delta(0.2);
social.perceived_liability_mut().add_delta(0.3);
social.self_hate_mut().add_delta(0.4);
social.perceived_competence_mut().add_delta(0.5);
assert!((social.loneliness().delta() - 0.1).abs() < f32::EPSILON);
assert!((social.perceived_reciprocal_caring().delta() - 0.2).abs() < f32::EPSILON);
assert!((social.perceived_liability().delta() - 0.3).abs() < f32::EPSILON);
assert!((social.self_hate().delta() - 0.4).abs() < f32::EPSILON);
assert!((social.perceived_competence().delta() - 0.5).abs() < f32::EPSILON);
}
#[test]
fn apply_decay_and_reset() {
let mut social = SocialCognition::new();
social.add_loneliness_delta(0.4);
social.add_perceived_reciprocal_caring_delta(0.4);
social.add_perceived_liability_delta(0.4);
social.add_self_hate_delta(0.4);
social.add_perceived_competence_delta(0.4);
social.apply_decay(Duration::days(1));
assert!(social.loneliness().delta() < 0.4);
social.reset_deltas();
assert!(social.loneliness().delta().abs() < f32::EPSILON);
assert!(social.perceived_reciprocal_caring().delta().abs() < f32::EPSILON);
assert!(social.perceived_liability().delta().abs() < f32::EPSILON);
assert!(social.self_hate().delta().abs() < f32::EPSILON);
assert!(social.perceived_competence().delta().abs() < f32::EPSILON);
}
#[test]
fn default_equals_new() {
let d = SocialCognition::default();
let n = SocialCognition::new();
assert_eq!(d, n);
}
#[test]
fn clone_and_equality() {
let s1 = SocialCognition::new().with_perceived_competence_base(0.8);
let s2 = s1.clone();
assert_eq!(s1, s2);
}
#[test]
fn debug_format() {
let social = SocialCognition::new();
let debug = format!("{:?}", social);
assert!(debug.contains("SocialCognition"));
}
}