use std::time::{SystemTime, UNIX_EPOCH};
use mr_common::types::DreamConfig;
use super::lock::DreamState;
#[derive(Debug, Clone, PartialEq)]
pub enum DreamGateResult {
Allowed,
Disabled,
LlmNotConfigured,
TooSoon {
hours_since_last: f64,
min_hours: f64,
},
NotEnoughNewMemories {
new_memories: usize,
min_new_memories: usize,
},
}
pub struct DreamGate;
impl DreamGate {
pub fn check(
config: &DreamConfig,
last_state: Option<&DreamState>,
new_user_memories: usize,
) -> DreamGateResult {
if !config.enabled {
return DreamGateResult::Disabled;
}
if let Some(state) = last_state {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
let hours_since_last = (now - state.last_run_at) as f64 / 3600.0;
if hours_since_last < config.min_hours_between {
return DreamGateResult::TooSoon {
hours_since_last,
min_hours: config.min_hours_between,
};
}
if new_user_memories < config.min_new_memories {
return DreamGateResult::NotEnoughNewMemories {
new_memories: new_user_memories,
min_new_memories: config.min_new_memories,
};
}
}
DreamGateResult::Allowed
}
}
#[cfg(test)]
mod tests {
use super::*;
fn make_config(enabled: bool, min_hours: f64) -> DreamConfig {
DreamConfig {
enabled,
min_hours_between: min_hours,
..Default::default()
}
}
fn make_state(hours_ago: f64, memory_count: u32) -> DreamState {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_secs() as i64;
DreamState {
last_run_at: now - (hours_ago * 3600.0) as i64,
memory_count,
}
}
#[test]
fn test_gate_disabled() {
let config = make_config(false, 24.0);
let result = DreamGate::check(&config, None, 10);
assert_eq!(result, DreamGateResult::Disabled);
}
#[test]
fn test_gate_allowed_no_state() {
let config = make_config(true, 24.0);
let result = DreamGate::check(&config, None, 10);
assert_eq!(result, DreamGateResult::Allowed);
}
#[test]
fn test_gate_too_soon() {
let config = make_config(true, 24.0);
let state = make_state(1.0, 5);
let result = DreamGate::check(&config, Some(&state), 10);
assert!(matches!(result, DreamGateResult::TooSoon { .. }));
}
#[test]
fn test_gate_allowed_after_time() {
let config = make_config(true, 24.0);
let state = make_state(30.0, 5);
let result = DreamGate::check(&config, Some(&state), 10);
assert_eq!(result, DreamGateResult::Allowed);
}
#[test]
fn test_gate_not_enough_new_memories() {
let config = make_config(true, 0.0);
let state = make_state(30.0, 10);
let result = DreamGate::check(&config, Some(&state), 0);
assert_eq!(
result,
DreamGateResult::NotEnoughNewMemories {
new_memories: 0,
min_new_memories: 1
}
);
}
#[test]
fn test_gate_allowed_with_new_memories() {
let config = make_config(true, 0.0);
let state = make_state(30.0, 10);
let result = DreamGate::check(&config, Some(&state), 2);
assert_eq!(result, DreamGateResult::Allowed);
}
#[test]
fn test_gate_custom_min_new_memories() {
let config = DreamConfig {
enabled: true,
min_hours_between: 0.0,
min_new_memories: 3,
..Default::default()
};
let state = make_state(30.0, 10);
let result = DreamGate::check(&config, Some(&state), 2);
assert!(matches!(
result,
DreamGateResult::NotEnoughNewMemories { .. }
));
let result = DreamGate::check(&config, Some(&state), 3);
assert_eq!(result, DreamGateResult::Allowed);
}
}