1use std::fs;
5use std::path::Path;
6
7#[derive(Clone, Debug)]
8pub struct HyperfocusState {
9 pub target: String,
10 pub target_type: String, pub intensity: f32, pub start_time_ms: u64,
13 pub depth_level: f32, pub efficiency: f32, 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, pub resource_concentration: f32, }
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 pub fn enter_hyperfocus(&mut self, target: &str, focus_type: &str) -> f32 {
43 let now = Self::now_ms();
44
45 self.attention_multiplier = 3.0; self.resource_concentration = 0.95; 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 pub fn process_data(&mut self, blocks_count: u32, complexity: f32) {
65 if let Some(focus) = &mut self.current_focus {
66 let type_bonus = match focus.target_type.as_str() {
68 "research" => 1.2, "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 focus.intensity = 0.95 + (blocks_count as f32 * 0.001).min(0.05);
81 }
82 }
83
84 pub fn exit_hyperfocus(&mut self) -> Option<HyperfocusState> {
86 if let Some(focus) = self.current_focus.take() {
87 self.focus_history.push(focus.clone());
89 if self.focus_history.len() > 100 {
90 self.focus_history.remove(0);
91 }
92
93 self.attention_multiplier = 1.0;
95 self.resource_concentration = 0.5;
96
97 return Some(focus);
98 }
99 None
100 }
101
102 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 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 pub fn get_resource_allocation(&self) -> (f32, f32) {
140 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 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); 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); }
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}