narrative_engine/schema/
relationship.rs1use rustc_hash::FxHashSet;
2use serde::{Deserialize, Serialize};
3
4use super::entity::EntityId;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct Relationship {
11 pub source: EntityId,
12 pub target: EntityId,
13 pub rel_type: String,
14 pub intensity: f32,
16 pub tags: FxHashSet<String>,
17}
18
19impl Relationship {
20 pub fn new(
22 source: EntityId,
23 target: EntityId,
24 rel_type: String,
25 intensity: f32,
26 tags: FxHashSet<String>,
27 ) -> Self {
28 Self {
29 source,
30 target,
31 rel_type,
32 intensity: intensity.clamp(0.0, 1.0),
33 tags,
34 }
35 }
36}
37
38#[cfg(test)]
39mod tests {
40 use super::*;
41
42 #[test]
43 fn relationship_creation() {
44 let rel = Relationship::new(
45 EntityId(1),
46 EntityId(2),
47 "rival".to_string(),
48 0.8,
49 FxHashSet::default(),
50 );
51 assert_eq!(rel.rel_type, "rival");
52 assert!((rel.intensity - 0.8).abs() < f32::EPSILON);
53 }
54
55 #[test]
56 fn intensity_clamped_high() {
57 let rel = Relationship::new(
58 EntityId(1),
59 EntityId(2),
60 "ally".to_string(),
61 1.5,
62 FxHashSet::default(),
63 );
64 assert!((rel.intensity - 1.0).abs() < f32::EPSILON);
65 }
66
67 #[test]
68 fn intensity_clamped_low() {
69 let rel = Relationship::new(
70 EntityId(1),
71 EntityId(2),
72 "stranger".to_string(),
73 -0.3,
74 FxHashSet::default(),
75 );
76 assert!((rel.intensity - 0.0).abs() < f32::EPSILON);
77 }
78
79 #[test]
80 fn relationship_with_tags() {
81 let mut tags = FxHashSet::default();
82 tags.insert("secret".to_string());
83 tags.insert("deteriorating".to_string());
84 let rel = Relationship::new(EntityId(1), EntityId(2), "lover".to_string(), 0.9, tags);
85 assert!(rel.tags.contains("secret"));
86 assert!(rel.tags.contains("deteriorating"));
87 assert_eq!(rel.tags.len(), 2);
88 }
89}