use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use uuid::Uuid;
#[derive(Debug)]
pub struct TemporalQualia {
clock_rate: f64,
base_rate: f64,
attention: f64,
novelty: f64,
time_crystals: Vec<TimeCrystal>,
binding_window: f64,
experience_buffer: VecDeque<TemporalEvent>,
subjective_duration: f64,
objective_duration: f64,
}
#[derive(Debug, Clone)]
pub struct TimeCrystal {
pub id: Uuid,
pub period: f64,
pub amplitude: f64,
pub phase: f64,
pub stability: f64,
pub content_pattern: Vec<f64>,
}
#[derive(Debug)]
pub struct SubjectiveTime {
now: f64,
specious_present: f64,
past: VecDeque<f64>,
anticipated: Vec<f64>,
mode: TimeMode,
}
#[derive(Debug, Clone, PartialEq)]
pub enum TimeMode {
Normal,
Dilated,
Compressed,
Flow,
Dissociated,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalEvent {
pub id: Uuid,
pub objective_time: f64,
pub subjective_time: f64,
pub information: f64,
pub arousal: f64,
pub novelty: f64,
}
impl TemporalQualia {
pub fn new() -> Self {
Self {
clock_rate: 1.0,
base_rate: 1.0,
attention: 0.5,
novelty: 0.5,
time_crystals: Vec::new(),
binding_window: 100.0, experience_buffer: VecDeque::with_capacity(1000),
subjective_duration: 0.0,
objective_duration: 0.0,
}
}
pub fn measure_dilation(&self) -> f64 {
if self.objective_duration > 0.0 {
self.subjective_duration / self.objective_duration
} else {
1.0
}
}
pub fn experience(&mut self, event: TemporalEvent) {
let dilation_factor = 1.0 + (event.novelty * 0.5) + (event.arousal * 0.3);
let attention_factor = 1.0 + (self.attention - 0.5) * 0.4;
self.clock_rate = self.base_rate * dilation_factor * attention_factor;
let obj_delta = 1.0; let subj_delta = obj_delta * self.clock_rate;
self.objective_duration += obj_delta;
self.subjective_duration += subj_delta;
self.novelty = self.novelty * 0.9 + event.novelty * 0.1;
self.experience_buffer.push_back(event);
if self.experience_buffer.len() > 1000 {
self.experience_buffer.pop_front();
}
}
pub fn set_attention(&mut self, attention: f64) {
self.attention = attention.clamp(0.0, 1.0);
}
pub fn enter_mode(&mut self, mode: TimeMode) {
match mode {
TimeMode::Normal => {
self.clock_rate = self.base_rate;
}
TimeMode::Dilated => {
self.clock_rate = self.base_rate * 2.0; }
TimeMode::Compressed => {
self.clock_rate = self.base_rate * 0.5; }
TimeMode::Flow => {
self.clock_rate = self.base_rate * 0.1;
}
TimeMode::Dissociated => {
self.clock_rate = 0.0; }
}
}
pub fn add_time_crystal(&mut self, period: f64, amplitude: f64, content: Vec<f64>) {
self.time_crystals.push(TimeCrystal {
id: Uuid::new_v4(),
period,
amplitude,
phase: 0.0,
stability: 0.5,
content_pattern: content,
});
}
pub fn crystal_contribution(&self, time: f64) -> f64 {
self.time_crystals
.iter()
.map(|crystal| {
let phase = (time / crystal.period + crystal.phase) * std::f64::consts::TAU;
crystal.amplitude * phase.sin() * crystal.stability
})
.sum()
}
pub fn subjective_elapsed(&self) -> f64 {
self.subjective_duration
}
pub fn objective_elapsed(&self) -> f64 {
self.objective_duration
}
pub fn current_clock_rate(&self) -> f64 {
self.clock_rate
}
pub fn temporal_binding(&self) -> Vec<Vec<&TemporalEvent>> {
let mut bindings: Vec<Vec<&TemporalEvent>> = Vec::new();
let mut current_binding: Vec<&TemporalEvent> = Vec::new();
let mut window_start = 0.0;
for event in &self.experience_buffer {
if event.objective_time - window_start <= self.binding_window {
current_binding.push(event);
} else {
if !current_binding.is_empty() {
bindings.push(current_binding);
current_binding = Vec::new();
}
window_start = event.objective_time;
current_binding.push(event);
}
}
if !current_binding.is_empty() {
bindings.push(current_binding);
}
bindings
}
pub fn statistics(&self) -> TemporalStatistics {
let avg_novelty = if self.experience_buffer.is_empty() {
0.0
} else {
self.experience_buffer
.iter()
.map(|e| e.novelty)
.sum::<f64>()
/ self.experience_buffer.len() as f64
};
TemporalStatistics {
dilation_factor: self.measure_dilation(),
clock_rate: self.clock_rate,
attention_level: self.attention,
average_novelty: avg_novelty,
crystal_count: self.time_crystals.len(),
experiences_buffered: self.experience_buffer.len(),
}
}
pub fn reset(&mut self) {
self.subjective_duration = 0.0;
self.objective_duration = 0.0;
self.clock_rate = self.base_rate;
self.experience_buffer.clear();
}
}
impl Default for TemporalQualia {
fn default() -> Self {
Self::new()
}
}
impl SubjectiveTime {
pub fn new() -> Self {
Self {
now: 0.0,
specious_present: 3.0, past: VecDeque::with_capacity(100),
anticipated: Vec::new(),
mode: TimeMode::Normal,
}
}
pub fn tick(&mut self, delta: f64) {
self.past.push_back(self.now);
if self.past.len() > 100 {
self.past.pop_front();
}
self.now += delta;
}
pub fn now(&self) -> f64 {
self.now
}
pub fn specious_present_range(&self) -> (f64, f64) {
let half = self.specious_present / 2.0;
(self.now - half, self.now + half)
}
pub fn anticipate(&mut self, future_moments: Vec<f64>) {
self.anticipated = future_moments;
}
pub fn accessible_past(&self) -> &VecDeque<f64> {
&self.past
}
pub fn set_mode(&mut self, mode: TimeMode) {
self.mode = mode;
}
pub fn mode(&self) -> &TimeMode {
&self.mode
}
pub fn estimate_duration(&self, start: f64, end: f64) -> f64 {
let objective = end - start;
match self.mode {
TimeMode::Normal => objective,
TimeMode::Dilated => objective * 2.0,
TimeMode::Compressed => objective * 0.5,
TimeMode::Flow => objective * 0.1,
TimeMode::Dissociated => 0.0,
}
}
}
impl Default for SubjectiveTime {
fn default() -> Self {
Self::new()
}
}
impl TimeCrystal {
pub fn new(period: f64, amplitude: f64) -> Self {
Self {
id: Uuid::new_v4(),
period,
amplitude,
phase: 0.0,
stability: 0.5,
content_pattern: Vec::new(),
}
}
pub fn value_at(&self, time: f64) -> f64 {
let phase = (time / self.period + self.phase) * std::f64::consts::TAU;
self.amplitude * phase.sin()
}
pub fn reinforce(&mut self) {
self.stability = (self.stability + 0.1).min(1.0);
}
pub fn decay(&mut self, factor: f64) {
self.stability *= factor;
}
}
#[derive(Debug, Clone)]
pub struct TemporalStatistics {
pub dilation_factor: f64,
pub clock_rate: f64,
pub attention_level: f64,
pub average_novelty: f64,
pub crystal_count: usize,
pub experiences_buffered: usize,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_temporal_qualia_creation() {
let tq = TemporalQualia::new();
assert_eq!(tq.measure_dilation(), 1.0); }
#[test]
fn test_time_dilation_with_novelty() {
let mut tq = TemporalQualia::new();
for i in 0..10 {
tq.experience(TemporalEvent {
id: Uuid::new_v4(),
objective_time: i as f64,
subjective_time: 0.0,
information: 0.5,
arousal: 0.7,
novelty: 0.9, });
}
assert!(tq.measure_dilation() > 1.0);
}
#[test]
fn test_time_compression_with_familiarity() {
let mut tq = TemporalQualia::new();
for i in 0..10 {
tq.experience(TemporalEvent {
id: Uuid::new_v4(),
objective_time: i as f64,
subjective_time: 0.0,
information: 0.1,
arousal: 0.1,
novelty: 0.1, });
}
let dilation = tq.measure_dilation();
assert!(dilation >= 1.0);
}
#[test]
fn test_time_modes() {
let mut tq = TemporalQualia::new();
let base = tq.current_clock_rate();
tq.enter_mode(TimeMode::Dilated);
assert!(tq.current_clock_rate() > base);
tq.enter_mode(TimeMode::Compressed);
assert!(tq.current_clock_rate() < base);
tq.enter_mode(TimeMode::Flow);
assert!(tq.current_clock_rate() < tq.base_rate);
}
#[test]
fn test_time_crystal() {
let crystal = TimeCrystal::new(10.0, 1.0);
let v1 = crystal.value_at(0.0);
let v2 = crystal.value_at(2.5); let v3 = crystal.value_at(5.0);
assert!((v1 - 0.0).abs() < 0.01); assert!(v2 > 0.9); assert!((v3 - 0.0).abs() < 0.01); }
#[test]
fn test_subjective_time() {
let mut st = SubjectiveTime::new();
st.tick(1.0);
st.tick(1.0);
st.tick(1.0);
assert_eq!(st.now(), 3.0);
assert_eq!(st.accessible_past().len(), 3);
}
#[test]
fn test_specious_present() {
let st = SubjectiveTime::new();
let (start, end) = st.specious_present_range();
assert!(end - start > 0.0); assert_eq!(end - start, st.specious_present); }
#[test]
fn test_temporal_statistics() {
let mut tq = TemporalQualia::new();
tq.add_time_crystal(5.0, 1.0, vec![0.1, 0.2]);
for i in 0..5 {
tq.experience(TemporalEvent {
id: Uuid::new_v4(),
objective_time: i as f64,
subjective_time: 0.0,
information: 0.5,
arousal: 0.5,
novelty: 0.5,
});
}
let stats = tq.statistics();
assert_eq!(stats.crystal_count, 1);
assert_eq!(stats.experiences_buffered, 5);
}
}