use std::fs;
use std::path::Path;
#[derive(Clone, Debug)]
pub struct HyperfocusState {
pub target: String,
pub target_type: String, pub intensity: f32, pub start_time_ms: u64,
pub depth_level: f32, pub efficiency: f32, pub blocks_processed: u32,
}
pub struct Hyperfocus {
pub current_focus: Option<HyperfocusState>,
pub focus_history: Vec<HyperfocusState>,
pub attention_multiplier: f32, pub resource_concentration: f32, }
impl Default for Hyperfocus {
fn default() -> Self {
Self::new()
}
}
impl Hyperfocus {
pub fn new() -> Self {
Self {
current_focus: None,
focus_history: Vec::new(),
attention_multiplier: 1.0,
resource_concentration: 0.5,
}
}
pub fn enter_hyperfocus(&mut self, target: &str, focus_type: &str) -> f32 {
let now = Self::now_ms();
self.attention_multiplier = 3.0; self.resource_concentration = 0.95;
let state = HyperfocusState {
target: target.to_string(),
target_type: focus_type.to_string(),
intensity: 1.0,
start_time_ms: now,
depth_level: 0.0,
efficiency: 0.8,
blocks_processed: 0,
};
self.current_focus = Some(state);
self.attention_multiplier
}
pub fn process_data(&mut self, blocks_count: u32, complexity: f32) {
if let Some(focus) = &mut self.current_focus {
let type_bonus = match focus.target_type.as_str() {
"research" => 1.2, "problem_solving" => 1.1,
"creative" => 0.9,
"planning" => 1.0,
_ => 1.0,
};
focus.efficiency = (focus.efficiency + 0.02 * type_bonus).min(1.0);
focus.depth_level = (focus.depth_level + 0.05 * complexity).min(1.0);
focus.blocks_processed += blocks_count;
focus.intensity = 0.95 + (blocks_count as f32 * 0.001).min(0.05);
}
}
pub fn exit_hyperfocus(&mut self) -> Option<HyperfocusState> {
if let Some(focus) = self.current_focus.take() {
self.focus_history.push(focus.clone());
if self.focus_history.len() > 100 {
self.focus_history.remove(0);
}
self.attention_multiplier = 1.0;
self.resource_concentration = 0.5;
return Some(focus);
}
None
}
pub fn get_insights(&self) -> Vec<String> {
let mut insights = Vec::new();
if let Some(focus) = &self.current_focus {
let mut insight = format!("Hyperfocus on '{}' ({})", focus.target, focus.target_type);
if focus.blocks_processed > 100 {
insight.push_str(&format!(" - Processed {} blocks", focus.blocks_processed));
}
if focus.depth_level > 0.7 {
insight.push_str(" - Deep understanding achieved");
} else if focus.depth_level > 0.4 {
insight.push_str(" - Moderate depth");
}
if focus.efficiency > 0.9 {
insight.push_str(" - High efficiency");
}
insights.push(insight);
}
insights
}
pub fn is_productive(&self) -> bool {
if let Some(focus) = &self.current_focus {
focus.intensity > 0.7 && focus.efficiency > 0.5
} else {
false
}
}
pub fn get_resource_allocation(&self) -> (f32, f32) {
if self.current_focus.is_some() {
(
self.resource_concentration,
1.0 - self.resource_concentration,
)
} else {
(0.5, 0.5)
}
}
pub fn stats(&self) -> (bool, f32, f32, u32) {
if let Some(focus) = &self.current_focus {
(
true,
focus.intensity,
focus.depth_level,
focus.blocks_processed,
)
} else {
(false, 0.0, 0.0, 0)
}
}
pub fn save(&self, dir: &Path) -> Result<(), String> {
let path = dir.join("hyperfocus.bin");
let mut data = Vec::new();
data.extend_from_slice(b"HYPF");
data.push(1);
if let Some(focus) = &self.current_focus {
data.push(1);
let target_bytes = focus.target.as_bytes();
data.extend_from_slice(&(target_bytes.len() as u16).to_le_bytes());
data.extend_from_slice(target_bytes);
let type_bytes = focus.target_type.as_bytes();
data.push(type_bytes.len() as u8);
data.extend_from_slice(type_bytes);
data.extend_from_slice(&focus.intensity.to_le_bytes());
data.extend_from_slice(&focus.start_time_ms.to_le_bytes());
data.extend_from_slice(&focus.depth_level.to_le_bytes());
data.extend_from_slice(&focus.efficiency.to_le_bytes());
data.extend_from_slice(&focus.blocks_processed.to_le_bytes());
} else {
data.push(0); }
let tmp_path = dir.join("hyperfocus.bin.tmp");
fs::write(&tmp_path, data).map_err(|e| e.to_string())?;
fs::rename(&tmp_path, &path).map_err(|e| e.to_string())
}
pub fn load(dir: &Path) -> Result<Self, String> {
let path = dir.join("hyperfocus.bin");
if !path.exists() {
return Ok(Self::new());
}
let data = fs::read(&path).map_err(|e| e.to_string())?;
if data.len() < 5 || &data[0..4] != b"HYPF" {
return Ok(Self::new());
}
let mut idx = 5;
let mut current_focus = None;
if idx < data.len() && data[idx] == 1 {
idx += 1;
if idx + 2 <= data.len() {
let target_len = u16::from_le_bytes([data[idx], data[idx + 1]]) as usize;
idx += 2;
if idx + target_len > data.len() {
return Ok(Self::new());
}
let target = String::from_utf8_lossy(&data[idx..idx + target_len]).to_string();
idx += target_len;
if idx >= data.len() {
return Ok(Self::new());
}
let type_len = data[idx] as usize;
idx += 1;
if idx + type_len > data.len() {
return Ok(Self::new());
}
let target_type = String::from_utf8_lossy(&data[idx..idx + type_len]).to_string();
idx += type_len;
if idx + 24 <= data.len() {
let intensity = f32::from_le_bytes([
data[idx],
data[idx + 1],
data[idx + 2],
data[idx + 3],
]);
idx += 4;
let start_time_ms = u64::from_le_bytes([
data[idx],
data[idx + 1],
data[idx + 2],
data[idx + 3],
data[idx + 4],
data[idx + 5],
data[idx + 6],
data[idx + 7],
]);
idx += 8;
let depth_level = f32::from_le_bytes([
data[idx],
data[idx + 1],
data[idx + 2],
data[idx + 3],
]);
idx += 4;
let efficiency = f32::from_le_bytes([
data[idx],
data[idx + 1],
data[idx + 2],
data[idx + 3],
]);
idx += 4;
let blocks_processed = u32::from_le_bytes([
data[idx],
data[idx + 1],
data[idx + 2],
data[idx + 3],
]);
current_focus = Some(HyperfocusState {
target,
target_type,
intensity,
start_time_ms,
depth_level,
efficiency,
blocks_processed,
});
}
}
}
let is_active = current_focus.is_some();
Ok(Self {
current_focus,
focus_history: Vec::new(),
attention_multiplier: if is_active { 3.0 } else { 1.0 },
resource_concentration: if is_active { 0.95 } else { 0.5 },
})
}
pub fn load_or_init(dir: &Path) -> Self {
Self::load(dir).unwrap_or_else(|_| Self::new())
}
fn now_ms() -> u64 {
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis() as u64
}
}