use crate::state::StateValue;
use crate::types::Duration;
const DEFAULT_DECAY_HALF_LIFE: Duration = Duration::days(14);
#[derive(Debug, Clone, PartialEq)]
pub struct DirectionalDimensions {
warmth: StateValue,
resentment: StateValue,
dependence: StateValue,
attraction: StateValue,
attachment: StateValue,
jealousy: StateValue,
fear: StateValue,
obligation: StateValue,
}
impl DirectionalDimensions {
#[must_use]
pub fn new() -> Self {
DirectionalDimensions {
warmth: StateValue::new(0.2)
.with_bounds(0.0, 1.0)
.with_decay_half_life(DEFAULT_DECAY_HALF_LIFE),
resentment: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(DEFAULT_DECAY_HALF_LIFE),
dependence: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(DEFAULT_DECAY_HALF_LIFE),
attraction: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(DEFAULT_DECAY_HALF_LIFE),
attachment: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Duration::days(30)), jealousy: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Duration::days(7)), fear: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Duration::days(7)), obligation: StateValue::new(0.0)
.with_bounds(0.0, 1.0)
.with_decay_half_life(Duration::days(30)), }
}
#[must_use]
pub fn warmth_effective(&self) -> f32 {
self.warmth.effective()
}
#[must_use]
pub fn resentment_effective(&self) -> f32 {
self.resentment.effective()
}
#[must_use]
pub fn dependence_effective(&self) -> f32 {
self.dependence.effective()
}
#[must_use]
pub fn attraction_effective(&self) -> f32 {
self.attraction.effective()
}
#[must_use]
pub fn attachment_effective(&self) -> f32 {
self.attachment.effective()
}
#[must_use]
pub fn jealousy_effective(&self) -> f32 {
self.jealousy.effective()
}
#[must_use]
pub fn fear_effective(&self) -> f32 {
self.fear.effective()
}
#[must_use]
pub fn obligation_effective(&self) -> f32 {
self.obligation.effective()
}
#[must_use]
pub fn warmth(&self) -> &StateValue {
&self.warmth
}
#[must_use]
pub fn resentment(&self) -> &StateValue {
&self.resentment
}
#[must_use]
pub fn dependence(&self) -> &StateValue {
&self.dependence
}
#[must_use]
pub fn attraction(&self) -> &StateValue {
&self.attraction
}
#[must_use]
pub fn attachment(&self) -> &StateValue {
&self.attachment
}
#[must_use]
pub fn jealousy(&self) -> &StateValue {
&self.jealousy
}
#[must_use]
pub fn fear(&self) -> &StateValue {
&self.fear
}
#[must_use]
pub fn obligation(&self) -> &StateValue {
&self.obligation
}
pub fn warmth_mut(&mut self) -> &mut StateValue {
&mut self.warmth
}
pub fn resentment_mut(&mut self) -> &mut StateValue {
&mut self.resentment
}
pub fn dependence_mut(&mut self) -> &mut StateValue {
&mut self.dependence
}
pub fn attraction_mut(&mut self) -> &mut StateValue {
&mut self.attraction
}
pub fn attachment_mut(&mut self) -> &mut StateValue {
&mut self.attachment
}
pub fn jealousy_mut(&mut self) -> &mut StateValue {
&mut self.jealousy
}
pub fn fear_mut(&mut self) -> &mut StateValue {
&mut self.fear
}
pub fn obligation_mut(&mut self) -> &mut StateValue {
&mut self.obligation
}
pub fn add_warmth_delta(&mut self, amount: f32) {
self.warmth.add_delta(amount);
}
pub fn add_resentment_delta(&mut self, amount: f32) {
self.resentment.add_delta(amount);
}
pub fn add_dependence_delta(&mut self, amount: f32) {
self.dependence.add_delta(amount);
}
pub fn add_attraction_delta(&mut self, amount: f32) {
self.attraction.add_delta(amount);
}
pub fn add_attachment_delta(&mut self, amount: f32) {
self.attachment.add_delta(amount);
}
pub fn add_jealousy_delta(&mut self, amount: f32) {
self.jealousy.add_delta(amount);
}
pub fn add_fear_delta(&mut self, amount: f32) {
self.fear.add_delta(amount);
}
pub fn add_obligation_delta(&mut self, amount: f32) {
self.obligation.add_delta(amount);
}
pub fn apply_decay(&mut self, elapsed: Duration) {
self.warmth.apply_decay(elapsed);
self.resentment.apply_decay(elapsed);
self.dependence.apply_decay(elapsed);
self.attraction.apply_decay(elapsed);
self.attachment.apply_decay(elapsed);
self.jealousy.apply_decay(elapsed);
self.fear.apply_decay(elapsed);
self.obligation.apply_decay(elapsed);
}
pub fn reset_deltas(&mut self) {
self.warmth.reset_delta();
self.resentment.reset_delta();
self.dependence.reset_delta();
self.attraction.reset_delta();
self.attachment.reset_delta();
self.jealousy.reset_delta();
self.fear.reset_delta();
self.obligation.reset_delta();
}
}
impl Default for DirectionalDimensions {
fn default() -> Self {
DirectionalDimensions::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_creates_default_values() {
let dims = DirectionalDimensions::new();
assert!((dims.warmth_effective() - 0.2).abs() < f32::EPSILON);
assert!(dims.resentment_effective().abs() < f32::EPSILON);
assert!(dims.dependence_effective().abs() < f32::EPSILON);
assert!(dims.attraction_effective().abs() < f32::EPSILON);
assert!(dims.attachment_effective().abs() < f32::EPSILON);
assert!(dims.jealousy_effective().abs() < f32::EPSILON);
assert!(dims.fear_effective().abs() < f32::EPSILON);
assert!(dims.obligation_effective().abs() < f32::EPSILON);
}
#[test]
fn add_warmth_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_warmth_delta(0.3);
assert!((dims.warmth().delta() - 0.3).abs() < f32::EPSILON);
}
#[test]
fn add_resentment_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_resentment_delta(0.4);
assert!((dims.resentment().delta() - 0.4).abs() < f32::EPSILON);
}
#[test]
fn add_dependence_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_dependence_delta(0.2);
assert!((dims.dependence().delta() - 0.2).abs() < f32::EPSILON);
}
#[test]
fn add_attraction_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_attraction_delta(0.5);
assert!((dims.attraction().delta() - 0.5).abs() < f32::EPSILON);
}
#[test]
fn add_attachment_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_attachment_delta(0.3);
assert!((dims.attachment().delta() - 0.3).abs() < f32::EPSILON);
}
#[test]
fn add_jealousy_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_jealousy_delta(0.2);
assert!((dims.jealousy().delta() - 0.2).abs() < f32::EPSILON);
}
#[test]
fn add_fear_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_fear_delta(0.4);
assert!((dims.fear().delta() - 0.4).abs() < f32::EPSILON);
}
#[test]
fn add_obligation_delta() {
let mut dims = DirectionalDimensions::new();
dims.add_obligation_delta(0.3);
assert!((dims.obligation().delta() - 0.3).abs() < f32::EPSILON);
}
#[test]
fn warmth_decays_over_14_days() {
let mut dims = DirectionalDimensions::new();
dims.add_warmth_delta(0.4);
dims.apply_decay(Duration::days(14));
assert!((dims.warmth().delta() - 0.2).abs() < 0.01);
}
#[test]
fn fear_decays_over_7_days() {
let mut dims = DirectionalDimensions::new();
dims.add_fear_delta(0.4);
dims.apply_decay(Duration::days(7));
assert!((dims.fear().delta() - 0.2).abs() < 0.01);
}
#[test]
fn jealousy_decays_over_7_days() {
let mut dims = DirectionalDimensions::new();
dims.add_jealousy_delta(0.4);
dims.apply_decay(Duration::days(7));
assert!((dims.jealousy().delta() - 0.2).abs() < 0.01);
}
#[test]
fn attachment_decays_over_30_days() {
let mut dims = DirectionalDimensions::new();
dims.add_attachment_delta(0.4);
dims.apply_decay(Duration::days(30));
assert!((dims.attachment().delta() - 0.2).abs() < 0.01);
}
#[test]
fn obligation_decays_over_30_days() {
let mut dims = DirectionalDimensions::new();
dims.add_obligation_delta(0.4);
dims.apply_decay(Duration::days(30));
assert!((dims.obligation().delta() - 0.2).abs() < 0.01);
}
#[test]
fn fear_decays_faster_than_warmth() {
let mut dims = DirectionalDimensions::new();
dims.add_fear_delta(0.4);
dims.add_warmth_delta(0.4);
dims.apply_decay(Duration::days(7));
assert!(dims.fear().delta() < dims.warmth().delta());
}
#[test]
fn reset_deltas() {
let mut dims = DirectionalDimensions::new();
dims.add_warmth_delta(0.3);
dims.add_fear_delta(0.2);
dims.reset_deltas();
assert!(dims.warmth().delta().abs() < f32::EPSILON);
assert!(dims.fear().delta().abs() < f32::EPSILON);
}
#[test]
fn mutable_references_work() {
let mut dims = DirectionalDimensions::new();
dims.warmth_mut().add_delta(0.1);
dims.resentment_mut().add_delta(0.2);
dims.dependence_mut().add_delta(0.3);
dims.attraction_mut().add_delta(0.4);
dims.attachment_mut().add_delta(0.5);
dims.jealousy_mut().add_delta(0.1);
dims.fear_mut().add_delta(0.2);
dims.obligation_mut().add_delta(0.3);
assert!((dims.warmth().delta() - 0.1).abs() < f32::EPSILON);
assert!((dims.resentment().delta() - 0.2).abs() < f32::EPSILON);
assert!((dims.dependence().delta() - 0.3).abs() < f32::EPSILON);
assert!((dims.attraction().delta() - 0.4).abs() < f32::EPSILON);
assert!((dims.attachment().delta() - 0.5).abs() < f32::EPSILON);
assert!((dims.jealousy().delta() - 0.1).abs() < f32::EPSILON);
assert!((dims.fear().delta() - 0.2).abs() < f32::EPSILON);
assert!((dims.obligation().delta() - 0.3).abs() < f32::EPSILON);
}
#[test]
fn default_equals_new() {
let d = DirectionalDimensions::default();
let n = DirectionalDimensions::new();
assert_eq!(d, n);
}
#[test]
fn clone_and_equality() {
let d1 = DirectionalDimensions::new();
let d2 = d1.clone();
assert_eq!(d1, d2);
}
#[test]
fn debug_format() {
let dims = DirectionalDimensions::new();
let debug = format!("{:?}", dims);
assert!(debug.contains("DirectionalDimensions"));
}
}