use crate::state::StateValue;
use crate::types::Duration;
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct AttachmentStyle {
anxiety: StateValue,
avoidance: StateValue,
}
impl AttachmentStyle {
const ATTACHMENT_DECAY_HALF_LIFE: Duration = Duration::years(1);
#[must_use]
pub fn new() -> Self {
AttachmentStyle {
anxiety: StateValue::new(0.2)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::ATTACHMENT_DECAY_HALF_LIFE),
avoidance: StateValue::new(0.2)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Self::ATTACHMENT_DECAY_HALF_LIFE),
}
}
#[must_use]
pub fn with_anxiety_base(mut self, value: f32) -> Self {
self.anxiety.set_base(value);
self
}
#[must_use]
pub fn with_avoidance_base(mut self, value: f32) -> Self {
self.avoidance.set_base(value);
self
}
#[must_use]
pub fn anxiety_effective(&self) -> f32 {
self.anxiety.effective()
}
#[must_use]
pub fn avoidance_effective(&self) -> f32 {
self.avoidance.effective()
}
#[must_use]
pub fn anxiety(&self) -> &StateValue {
&self.anxiety
}
pub fn anxiety_mut(&mut self) -> &mut StateValue {
&mut self.anxiety
}
#[must_use]
pub fn avoidance(&self) -> &StateValue {
&self.avoidance
}
pub fn avoidance_mut(&mut self) -> &mut StateValue {
&mut self.avoidance
}
pub fn add_anxiety_delta(&mut self, delta: f32) {
self.anxiety.add_delta(delta);
}
pub fn add_avoidance_delta(&mut self, delta: f32) {
self.avoidance.add_delta(delta);
}
pub fn apply_decay(&mut self, elapsed: Duration) {
self.anxiety.apply_decay(elapsed);
self.avoidance.apply_decay(elapsed);
}
pub fn reset_deltas(&mut self) {
self.anxiety.reset_delta();
self.avoidance.reset_delta();
}
}
impl Default for AttachmentStyle {
fn default() -> Self {
AttachmentStyle::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn default_is_secure_low() {
let attachment = AttachmentStyle::new();
assert!(attachment.anxiety_effective() < 0.3);
assert!(attachment.avoidance_effective() < 0.3);
}
#[test]
fn builder_methods_work() {
let attachment = AttachmentStyle::new()
.with_anxiety_base(0.6)
.with_avoidance_base(0.4);
assert!((attachment.anxiety().base() - 0.6).abs() < f32::EPSILON);
assert!((attachment.avoidance().base() - 0.4).abs() < f32::EPSILON);
}
#[test]
fn apply_decay_reduces_deltas() {
let mut attachment = AttachmentStyle::new();
attachment.add_anxiety_delta(0.6);
attachment.add_avoidance_delta(0.6);
attachment.apply_decay(Duration::years(1));
assert!(attachment.anxiety().delta() < 0.6);
assert!(attachment.avoidance().delta() < 0.6);
}
#[test]
fn reset_deltas_clears_values() {
let mut attachment = AttachmentStyle::new();
attachment.add_anxiety_delta(0.4);
attachment.add_avoidance_delta(-0.2);
attachment.reset_deltas();
assert!(attachment.anxiety().delta().abs() < f32::EPSILON);
assert!(attachment.avoidance().delta().abs() < f32::EPSILON);
}
#[test]
fn clone_and_equality() {
let attachment = AttachmentStyle::new();
let cloned = attachment.clone();
assert_eq!(attachment, cloned);
}
#[test]
fn debug_format() {
let attachment = AttachmentStyle::new();
let debug = format!("{:?}", attachment);
assert!(debug.contains("AttachmentStyle"));
}
#[test]
fn mutable_accessors_update_state_values() {
let mut attachment = AttachmentStyle::default();
attachment.anxiety_mut().set_base(0.7);
attachment.avoidance_mut().set_base(0.6);
assert!((attachment.anxiety().base() - 0.7).abs() < f32::EPSILON);
assert!((attachment.avoidance().base() - 0.6).abs() < f32::EPSILON);
}
}