microscope_memory/
impulse_control.rs1use std::collections::HashSet;
5use std::sync::{Arc, RwLock};
6use std::time::{SystemTime, UNIX_EPOCH};
7
8#[derive(Debug, Clone)]
10pub struct Stimulus {
11 pub id: String,
12 pub content: String,
13 pub source: String,
14 pub urgency: f32, pub relevance: f32, pub timestamp: u64,
17 pub suppressed: bool,
18}
19
20pub struct ImpulseControl {
22 #[allow(dead_code)]
23 attention_gates: Arc<RwLock<Vec<String>>>,
24 suppression_patterns: Arc<RwLock<HashSet<String>>>,
25 long_term_goals: Vec<String>,
26 attention_budget: f32, suppression_threshold: f32,
28}
29
30impl Default for ImpulseControl {
31 fn default() -> Self {
32 Self::new()
33 }
34}
35
36impl ImpulseControl {
37 pub fn new() -> Self {
39 Self {
40 attention_gates: Arc::new(RwLock::new(vec![
41 "urgent".to_string(),
42 "important".to_string(),
43 "goal_aligned".to_string(),
44 ])),
45 suppression_patterns: Arc::new(RwLock::new(HashSet::new())),
46 long_term_goals: Vec::new(),
47 attention_budget: 0.8, suppression_threshold: 0.3,
49 }
50 }
51
52 pub fn add_goal(&mut self, goal: &str) {
54 self.long_term_goals.push(goal.to_string());
55 }
56
57 pub fn add_suppression_pattern(&mut self, pattern: &str) {
59 crate::sync_guard::write_lock(&self.suppression_patterns).insert(pattern.to_lowercase());
60 }
61
62 pub fn filter_stimulus(&mut self, content: &str, source: &str, urgency: f32) -> Stimulus {
64 let id = format!("stimulus_{}", rand::random::<u32>());
65 let timestamp = SystemTime::now()
66 .duration_since(UNIX_EPOCH)
67 .unwrap()
68 .as_secs();
69
70 let mut suppressed = false;
71 let mut relevance = self.calculate_relevance(content);
72
73 let content_lower = content.to_lowercase();
75 let patterns = crate::sync_guard::read_lock(&self.suppression_patterns);
76 for pattern in patterns.iter() {
77 if content_lower.contains(pattern) {
78 suppressed = true;
79 relevance = 0.0; break;
81 }
82 }
83
84 if !suppressed && self.attention_budget < 0.2 {
86 if relevance < self.suppression_threshold * 2.0 {
88 suppressed = true;
89 }
90 }
91
92 let stimulus = Stimulus {
93 id,
94 content: content.to_string(),
95 source: source.to_string(),
96 urgency,
97 relevance,
98 timestamp,
99 suppressed,
100 };
101
102 if !stimulus.suppressed && stimulus.relevance > 0.5 {
104 self.attention_budget -= 0.1; self.attention_budget = self.attention_budget.max(0.0);
106 }
107
108 stimulus
109 }
110
111 fn calculate_relevance(&self, content: &str) -> f32 {
113 if self.long_term_goals.is_empty() {
114 return 0.5; }
116
117 let content_lower = content.to_lowercase();
118 let mut score = 0.0;
119
120 for goal in &self.long_term_goals {
121 let goal_lower = goal.to_lowercase();
122 if content_lower.contains(&goal_lower) {
123 score += 1.0;
124 }
125 }
126
127 let goal_keywords = ["achieve", "progress", "improve", "develop", "complete"];
129 for keyword in &goal_keywords {
130 if content_lower.contains(keyword) {
131 score += 0.5;
132 }
133 }
134
135 (score / (self.long_term_goals.len() as f32 + goal_keywords.len() as f32)).min(1.0)
136 }
137
138 pub fn restore_attention(&mut self, amount: f32) {
140 self.attention_budget += amount;
141 self.attention_budget = self.attention_budget.min(1.0);
142 }
143
144 pub fn get_stats(&self) -> (f32, usize) {
146 let patterns = crate::sync_guard::read_lock(&self.suppression_patterns);
147 (self.attention_budget, patterns.len())
148 }
149
150 pub fn clear_patterns(&mut self) {
152 crate::sync_guard::write_lock(&self.suppression_patterns).clear();
153 }
154}
155
156pub fn batch_filter_stimuli(
158 control: &mut ImpulseControl,
159 stimuli: &[(&str, &str, f32)],
160) -> Vec<Stimulus> {
161 stimuli
162 .iter()
163 .map(|(content, source, urgency)| control.filter_stimulus(content, source, *urgency))
164 .collect()
165}