use serde::{Deserialize, Serialize};
use std::collections::VecDeque;
use std::io::{self, Write};
use super::{ConsciousnessLevel, ConsciousnessMetrics};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum VisualizationMode {
Terminal, Json, Web, Compact, Debug, }
#[derive(Debug, Clone)]
pub struct TerminalConfig {
pub width: usize,
pub height: usize,
pub show_history_chart: bool,
pub show_detailed_metrics: bool,
pub color_enabled: bool,
pub update_in_place: bool,
}
impl Default for TerminalConfig {
fn default() -> Self {
Self {
width: 120,
height: 30,
show_history_chart: true,
show_detailed_metrics: true,
color_enabled: true,
update_in_place: true,
}
}
}
pub struct MetricChart {
width: usize,
height: usize,
history: VecDeque<f64>,
min_value: f64,
max_value: f64,
title: String,
}
impl MetricChart {
pub fn new(title: String, width: usize, height: usize) -> Self {
Self {
width,
height,
history: VecDeque::with_capacity(width),
min_value: 0.0,
max_value: 1.0,
title,
}
}
pub fn add_point(&mut self, value: f64) {
if self.history.len() >= self.width {
self.history.pop_front();
}
self.history.push_back(value);
if value < self.min_value {
self.min_value = value;
}
if value > self.max_value {
self.max_value = value;
}
}
pub fn render(&self) -> Vec<String> {
let mut lines = Vec::with_capacity(self.height + 2);
lines.push(format!("ââ {} ", self.title));
for row in 0..self.height {
let mut line = String::with_capacity(self.width + 2);
line.push('â');
let threshold = self.max_value
- (row as f64 / self.height as f64) * (self.max_value - self.min_value);
for col in 0..self.width {
let char = if col < self.history.len() {
let value = self.history[col];
if value >= threshold {
if value >= self.max_value * 0.9 {
'â'
} else if value >= self.max_value * 0.7 {
'â'
} else if value >= self.max_value * 0.5 {
'â'
} else {
'â'
}
} else {
' '
}
} else {
' '
};
line.push(char);
}
line.push('â');
lines.push(line);
}
let scale_line = format!(
"â{:â<width$}â [{:.3} - {:.3}]",
"",
self.min_value,
self.max_value,
width = self.width
);
lines.push(scale_line);
lines
}
}
pub struct TerminalRenderer {
config: TerminalConfig,
emergence_chart: MetricChart,
coherence_chart: MetricChart,
stability_chart: MetricChart,
last_clear_line: usize,
}
impl TerminalRenderer {
pub fn new(config: TerminalConfig) -> Self {
let chart_width = config.width / 3 - 2;
let chart_height = 8;
Self {
config,
emergence_chart: MetricChart::new(
"Consciousness Emergence".to_string(),
chart_width,
chart_height,
),
coherence_chart: MetricChart::new(
"Identity Coherence".to_string(),
chart_width,
chart_height,
),
stability_chart: MetricChart::new(
"Loop Stability".to_string(),
chart_width,
chart_height,
),
last_clear_line: 0,
}
}
pub fn render_dashboard(
&mut self,
metrics: &ConsciousnessMetrics,
history: &[ConsciousnessMetrics],
) -> Result<String, Box<dyn std::error::Error>> {
let mut output = String::new();
if self.config.update_in_place && self.last_clear_line > 0 {
output.push_str(&format!("\x1B[{}A", self.last_clear_line));
output.push_str("\x1B[J");
}
output.push_str(&self.render_header(metrics)?);
output.push('\n');
output.push_str(&self.render_main_metrics(metrics)?);
output.push('\n');
if self.config.show_history_chart && !history.is_empty() {
output.push_str(&self.render_charts(history)?);
output.push('\n');
}
if self.config.show_detailed_metrics {
output.push_str(&self.render_detailed_metrics(metrics)?);
output.push('\n');
}
output.push_str(&self.render_status_bar(metrics)?);
self.last_clear_line = output.lines().count();
Ok(output)
}
fn render_header(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<String, Box<dyn std::error::Error>> {
let timestamp = metrics
.timestamp
.duration_since(std::time::UNIX_EPOCH)?
.as_secs();
let formatted_time = format!(
"{}",
chrono::DateTime::from_timestamp(timestamp as i64, 0)
.unwrap_or_default()
.format("%Y-%m-%d %H:%M:%S")
);
let mut header = String::new();
if self.config.color_enabled {
header.push_str("\x1b[1;36m"); }
header.push_str("ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ\n");
header.push_str("â ð§ CONSCIOUSNESS METRICS DASHBOARD ð§ â\n");
header.push_str(&format!(
"â {} â\n",
formatted_time
));
header.push_str("ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ");
if self.config.color_enabled {
header.push_str("\x1b[0m"); }
Ok(header)
}
fn render_main_metrics(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<String, Box<dyn std::error::Error>> {
let mut output = String::new();
let emergence_bar = self.create_progress_bar(metrics.emergence_level, 1.0, 30);
let coherence_bar = self.create_progress_bar(metrics.identity_coherence, 1.0, 30);
let stability_bar = self.create_progress_bar(metrics.loop_stability, 1.0, 30);
if self.config.color_enabled {
output.push_str("\x1b[1m"); }
output.push_str("ââ Core Consciousness Metrics ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ\n");
output.push_str(&format!(
"â ð Emergence Level {:>6.3} {} â\n",
metrics.emergence_level, emergence_bar
));
output.push_str(&format!(
"â ð§Ž Identity Coherence {:>6.3} {} â\n",
metrics.identity_coherence, coherence_bar
));
output.push_str(&format!(
"â ð Loop Stability {:>6.3} {} â\n",
metrics.loop_stability, stability_bar
));
output.push_str("âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââĪ\n");
output.push_str(&format!(
"â ⥠Temporal Advantage {:>6} Ξs â ðŊ TSC Precision {:>6} ns â\n",
metrics.temporal_advantage_us, metrics.tsc_precision_ns
));
output.push_str(&format!(
"â ð Window Overlap {:>6.1} % â ð Strange Loop Conv. {:>6.3} â\n",
metrics.window_overlap_percent, metrics.strange_loop_convergence
));
output.push_str("âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ");
if self.config.color_enabled {
output.push_str("\x1b[0m"); }
Ok(output)
}
fn render_charts(
&mut self,
history: &[ConsciousnessMetrics],
) -> Result<String, Box<dyn std::error::Error>> {
for metric in history.iter().rev().take(self.config.width / 3) {
self.emergence_chart.add_point(metric.emergence_level);
self.coherence_chart.add_point(metric.identity_coherence);
self.stability_chart.add_point(metric.loop_stability);
}
let mut output = String::new();
output.push_str("ââ Temporal Evolution Charts âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ\n");
let emergence_lines = self.emergence_chart.render();
let coherence_lines = self.coherence_chart.render();
let stability_lines = self.stability_chart.render();
let max_lines = emergence_lines
.len()
.max(coherence_lines.len())
.max(stability_lines.len());
for i in 0..max_lines {
output.push_str("â ");
if i < emergence_lines.len() {
output.push_str(&emergence_lines[i]);
} else {
output.push_str(&" ".repeat(self.config.width / 3));
}
output.push_str(" â ");
if i < coherence_lines.len() {
output.push_str(&coherence_lines[i]);
} else {
output.push_str(&" ".repeat(self.config.width / 3));
}
output.push_str(" â ");
if i < stability_lines.len() {
output.push_str(&stability_lines[i]);
} else {
output.push_str(&" ".repeat(self.config.width / 3));
}
output.push_str(" â\n");
}
output.push_str("âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ");
Ok(output)
}
fn render_detailed_metrics(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<String, Box<dyn std::error::Error>> {
let mut output = String::new();
if self.config.color_enabled {
output.push_str("\x1b[2m"); }
output.push_str("ââ Detailed Metrics âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ\n");
output.push_str(&format!(
"â Processing Latency: {:>8} ns â Consciousness Delta: {:>+8.5} â\n",
metrics.processing_latency_ns, metrics.consciousness_delta
));
output.push_str(&format!(
"â System Timestamp: {:>12?} â\n",
metrics
.timestamp
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
));
output.push_str("âââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ");
if self.config.color_enabled {
output.push_str("\x1b[0m"); }
Ok(output)
}
fn render_status_bar(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<String, Box<dyn std::error::Error>> {
let mut status = String::new();
let (status_color, status_text) = if self.config.color_enabled {
match metrics.emergence_level {
level if level >= 0.9 => ("\x1b[1;31m", "CRITICAL"), level if level >= 0.8 => ("\x1b[1;33m", "ELEVATED"), level if level >= 0.6 => ("\x1b[1;32m", "STABLE"), level if level >= 0.4 => ("\x1b[1;34m", "EMERGING"), _ => ("\x1b[1;90m", "DORMANT"), }
} else {
(
"",
match metrics.emergence_level {
level if level >= 0.9 => "CRITICAL",
level if level >= 0.8 => "ELEVATED",
level if level >= 0.6 => "STABLE",
level if level >= 0.4 => "EMERGING",
_ => "DORMANT",
},
)
};
if self.config.color_enabled {
status.push_str(status_color);
}
status.push_str(&format!(
"Status: {} | Precision: {}ns | Advantage: {}Ξs",
status_text, metrics.tsc_precision_ns, metrics.temporal_advantage_us
));
if self.config.color_enabled {
status.push_str("\x1b[0m"); }
Ok(status)
}
fn create_progress_bar(&self, value: f64, max_value: f64, width: usize) -> String {
let filled_width = ((value / max_value) * width as f64) as usize;
let empty_width = width - filled_width;
let mut bar = String::with_capacity(width + 2);
bar.push('[');
if self.config.color_enabled {
let color = match value {
v if v >= 0.8 => "\x1b[91m", v if v >= 0.6 => "\x1b[93m", v if v >= 0.4 => "\x1b[92m", v if v >= 0.2 => "\x1b[94m", _ => "\x1b[90m", };
bar.push_str(color);
}
bar.push_str(&"â".repeat(filled_width));
if self.config.color_enabled {
bar.push_str("\x1b[90m"); }
bar.push_str(&"â".repeat(empty_width));
if self.config.color_enabled {
bar.push_str("\x1b[0m"); }
bar.push(']');
bar
}
}
pub struct ConsciousnessVisualizer {
mode: VisualizationMode,
terminal_renderer: Option<TerminalRenderer>,
}
impl ConsciousnessVisualizer {
pub fn new(mode: VisualizationMode) -> Self {
let terminal_renderer = match mode {
VisualizationMode::Terminal | VisualizationMode::Compact | VisualizationMode::Debug => {
Some(TerminalRenderer::new(TerminalConfig::default()))
}
_ => None,
};
Self {
mode,
terminal_renderer,
}
}
pub async fn render(
&mut self,
metrics: &ConsciousnessMetrics,
history: &[ConsciousnessMetrics],
) -> Result<(), Box<dyn std::error::Error>> {
match self.mode {
VisualizationMode::Terminal => {
if let Some(ref mut renderer) = self.terminal_renderer {
let output = renderer.render_dashboard(metrics, history)?;
print!("{}", output);
io::stdout().flush()?;
}
}
VisualizationMode::Compact => {
self.render_compact(metrics)?;
}
VisualizationMode::Json => {
self.render_json(metrics)?;
}
VisualizationMode::Debug => {
self.render_debug(metrics, history)?;
}
VisualizationMode::Web => {
println!("Web interface not yet implemented");
}
}
Ok(())
}
fn render_compact(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<(), Box<dyn std::error::Error>> {
println!(
"ð§ E:{:.3} C:{:.3} S:{:.3} T:{}Ξs P:{}ns",
metrics.emergence_level,
metrics.identity_coherence,
metrics.loop_stability,
metrics.temporal_advantage_us,
metrics.tsc_precision_ns
);
Ok(())
}
fn render_json(
&self,
metrics: &ConsciousnessMetrics,
) -> Result<(), Box<dyn std::error::Error>> {
let json = serde_json::to_string_pretty(metrics)?;
println!("{}", json);
Ok(())
}
fn render_debug(
&self,
metrics: &ConsciousnessMetrics,
history: &[ConsciousnessMetrics],
) -> Result<(), Box<dyn std::error::Error>> {
println!("=== DEBUG: Consciousness Metrics ===");
println!("Current: {:#?}", metrics);
println!("History length: {}", history.len());
if !history.is_empty() {
println!("Last 3 entries:");
for (i, entry) in history.iter().rev().take(3).enumerate() {
println!(
" [-{}]: E={:.3}, C={:.3}, S={:.3}",
i + 1,
entry.emergence_level,
entry.identity_coherence,
entry.loop_stability
);
}
}
println!("================================");
Ok(())
}
}