Skip to main content

microscope_memory/
hyperfocus.rs

1//! Hyperfocus — concentrated attention on single objective
2//! Redirects all system resources to one focus point: planning, problem-solving, creative depth, research
3
4use std::fs;
5use std::path::Path;
6
7#[derive(Clone, Debug)]
8pub struct HyperfocusState {
9    pub target: String,
10    pub target_type: String, // "planning", "problem_solving", "creative", "research"
11    pub intensity: f32,      // 0.0-1.0, how concentrated
12    pub start_time_ms: u64,
13    pub depth_level: f32, // how deep in the topic (0.0-1.0)
14    pub efficiency: f32,  // data processing efficiency
15    pub blocks_processed: u32,
16}
17
18pub struct Hyperfocus {
19    pub current_focus: Option<HyperfocusState>,
20    pub focus_history: Vec<HyperfocusState>,
21    pub attention_multiplier: f32, // base 1.0, up to 3.0 in hyperfocus
22    pub resource_concentration: f32, // how much goes to focus (0.5-1.0)
23}
24
25impl Default for Hyperfocus {
26    fn default() -> Self {
27        Self::new()
28    }
29}
30
31impl Hyperfocus {
32    pub fn new() -> Self {
33        Self {
34            current_focus: None,
35            focus_history: Vec::new(),
36            attention_multiplier: 1.0,
37            resource_concentration: 0.5,
38        }
39    }
40
41    /// Enter hyperfocus state on a specific target
42    pub fn enter_hyperfocus(&mut self, target: &str, focus_type: &str) -> f32 {
43        let now = Self::now_ms();
44
45        // Ramp up attention and resources
46        self.attention_multiplier = 3.0; // 3x normal
47        self.resource_concentration = 0.95; // 95% to this task
48
49        let state = HyperfocusState {
50            target: target.to_string(),
51            target_type: focus_type.to_string(),
52            intensity: 1.0,
53            start_time_ms: now,
54            depth_level: 0.0,
55            efficiency: 0.8,
56            blocks_processed: 0,
57        };
58
59        self.current_focus = Some(state);
60        self.attention_multiplier
61    }
62
63    /// Process data during hyperfocus (deepen understanding)
64    pub fn process_data(&mut self, blocks_count: u32, complexity: f32) {
65        if let Some(focus) = &mut self.current_focus {
66            // Efficiency increases with focus type
67            let type_bonus = match focus.target_type.as_str() {
68                "research" => 1.2, // best for data processing
69                "problem_solving" => 1.1,
70                "creative" => 0.9,
71                "planning" => 1.0,
72                _ => 1.0,
73            };
74
75            focus.efficiency = (focus.efficiency + 0.02 * type_bonus).min(1.0);
76            focus.depth_level = (focus.depth_level + 0.05 * complexity).min(1.0);
77            focus.blocks_processed += blocks_count;
78
79            // Intensity sustained at high level
80            focus.intensity = 0.95 + (blocks_count as f32 * 0.001).min(0.05);
81        }
82    }
83
84    /// Exit hyperfocus (save state and insights)
85    pub fn exit_hyperfocus(&mut self) -> Option<HyperfocusState> {
86        if let Some(focus) = self.current_focus.take() {
87            // Save to history
88            self.focus_history.push(focus.clone());
89            if self.focus_history.len() > 100 {
90                self.focus_history.remove(0);
91            }
92
93            // Return to normal
94            self.attention_multiplier = 1.0;
95            self.resource_concentration = 0.5;
96
97            return Some(focus);
98        }
99        None
100    }
101
102    /// Get hyperfocus insights (what was learned)
103    pub fn get_insights(&self) -> Vec<String> {
104        let mut insights = Vec::new();
105
106        if let Some(focus) = &self.current_focus {
107            let mut insight = format!("Hyperfocus on '{}' ({})", focus.target, focus.target_type);
108
109            if focus.blocks_processed > 100 {
110                insight.push_str(&format!(" - Processed {} blocks", focus.blocks_processed));
111            }
112
113            if focus.depth_level > 0.7 {
114                insight.push_str(" - Deep understanding achieved");
115            } else if focus.depth_level > 0.4 {
116                insight.push_str(" - Moderate depth");
117            }
118
119            if focus.efficiency > 0.9 {
120                insight.push_str(" - High efficiency");
121            }
122
123            insights.push(insight);
124        }
125
126        insights
127    }
128
129    /// Check if hyperfocus is still active and productive
130    pub fn is_productive(&self) -> bool {
131        if let Some(focus) = &self.current_focus {
132            focus.intensity > 0.7 && focus.efficiency > 0.5
133        } else {
134            false
135        }
136    }
137
138    /// Get resource allocation (how much goes to different tasks)
139    pub fn get_resource_allocation(&self) -> (f32, f32) {
140        // (to_focus, to_background)
141        if self.current_focus.is_some() {
142            (
143                self.resource_concentration,
144                1.0 - self.resource_concentration,
145            )
146        } else {
147            (0.5, 0.5)
148        }
149    }
150
151    /// Get stats
152    pub fn stats(&self) -> (bool, f32, f32, u32) {
153        if let Some(focus) = &self.current_focus {
154            (
155                true,
156                focus.intensity,
157                focus.depth_level,
158                focus.blocks_processed,
159            )
160        } else {
161            (false, 0.0, 0.0, 0)
162        }
163    }
164
165    pub fn save(&self, dir: &Path) -> Result<(), String> {
166        let path = dir.join("hyperfocus.bin");
167        let mut data = Vec::new();
168
169        data.extend_from_slice(b"HYPF");
170        data.push(1);
171
172        if let Some(focus) = &self.current_focus {
173            data.push(1); // Active
174
175            let target_bytes = focus.target.as_bytes();
176            data.extend_from_slice(&(target_bytes.len() as u16).to_le_bytes());
177            data.extend_from_slice(target_bytes);
178
179            let type_bytes = focus.target_type.as_bytes();
180            data.push(type_bytes.len() as u8);
181            data.extend_from_slice(type_bytes);
182
183            data.extend_from_slice(&focus.intensity.to_le_bytes());
184            data.extend_from_slice(&focus.start_time_ms.to_le_bytes());
185            data.extend_from_slice(&focus.depth_level.to_le_bytes());
186            data.extend_from_slice(&focus.efficiency.to_le_bytes());
187            data.extend_from_slice(&focus.blocks_processed.to_le_bytes());
188        } else {
189            data.push(0); // Inactive
190        }
191
192        let tmp_path = dir.join("hyperfocus.bin.tmp");
193        fs::write(&tmp_path, data).map_err(|e| e.to_string())?;
194        fs::rename(&tmp_path, &path).map_err(|e| e.to_string())
195    }
196
197    pub fn load(dir: &Path) -> Result<Self, String> {
198        let path = dir.join("hyperfocus.bin");
199        if !path.exists() {
200            return Ok(Self::new());
201        }
202
203        let data = fs::read(&path).map_err(|e| e.to_string())?;
204        if data.len() < 5 || &data[0..4] != b"HYPF" {
205            return Ok(Self::new());
206        }
207
208        let mut idx = 5;
209        let mut current_focus = None;
210
211        if idx < data.len() && data[idx] == 1 {
212            idx += 1;
213
214            if idx + 2 <= data.len() {
215                let target_len = u16::from_le_bytes([data[idx], data[idx + 1]]) as usize;
216                idx += 2;
217
218                if idx + target_len > data.len() {
219                    return Ok(Self::new());
220                }
221                let target = String::from_utf8_lossy(&data[idx..idx + target_len]).to_string();
222                idx += target_len;
223
224                if idx >= data.len() {
225                    return Ok(Self::new());
226                }
227                let type_len = data[idx] as usize;
228                idx += 1;
229
230                if idx + type_len > data.len() {
231                    return Ok(Self::new());
232                }
233                let target_type = String::from_utf8_lossy(&data[idx..idx + type_len]).to_string();
234                idx += type_len;
235
236                if idx + 24 <= data.len() {
237                    let intensity = f32::from_le_bytes([
238                        data[idx],
239                        data[idx + 1],
240                        data[idx + 2],
241                        data[idx + 3],
242                    ]);
243                    idx += 4;
244                    let start_time_ms = u64::from_le_bytes([
245                        data[idx],
246                        data[idx + 1],
247                        data[idx + 2],
248                        data[idx + 3],
249                        data[idx + 4],
250                        data[idx + 5],
251                        data[idx + 6],
252                        data[idx + 7],
253                    ]);
254                    idx += 8;
255                    let depth_level = f32::from_le_bytes([
256                        data[idx],
257                        data[idx + 1],
258                        data[idx + 2],
259                        data[idx + 3],
260                    ]);
261                    idx += 4;
262                    let efficiency = f32::from_le_bytes([
263                        data[idx],
264                        data[idx + 1],
265                        data[idx + 2],
266                        data[idx + 3],
267                    ]);
268                    idx += 4;
269                    let blocks_processed = u32::from_le_bytes([
270                        data[idx],
271                        data[idx + 1],
272                        data[idx + 2],
273                        data[idx + 3],
274                    ]);
275
276                    current_focus = Some(HyperfocusState {
277                        target,
278                        target_type,
279                        intensity,
280                        start_time_ms,
281                        depth_level,
282                        efficiency,
283                        blocks_processed,
284                    });
285                }
286            }
287        }
288
289        let is_active = current_focus.is_some();
290        Ok(Self {
291            current_focus,
292            focus_history: Vec::new(),
293            attention_multiplier: if is_active { 3.0 } else { 1.0 },
294            resource_concentration: if is_active { 0.95 } else { 0.5 },
295        })
296    }
297
298    pub fn load_or_init(dir: &Path) -> Self {
299        Self::load(dir).unwrap_or_else(|_| Self::new())
300    }
301
302    fn now_ms() -> u64 {
303        std::time::SystemTime::now()
304            .duration_since(std::time::UNIX_EPOCH)
305            .unwrap_or_default()
306            .as_millis() as u64
307    }
308}