use colored::Colorize;
use crate::display::icons;
pub struct StaticDagTask {
pub id: String,
pub verb: String,
pub layer: usize,
}
pub struct StaticDagEdge {
pub from: String,
pub to: String,
}
pub fn print_static_dag(tasks: &[StaticDagTask], edges: &[StaticDagEdge]) {
if tasks.is_empty() {
return;
}
let max_layer = tasks.iter().map(|t| t.layer).max().unwrap_or(0);
let num_layers = max_layer + 1;
let summary = format!(
"DAG {} tasks \u{00B7} {} layers \u{00B7} {} edges",
tasks.len(),
num_layers,
edges.len()
);
println!(" {}", summary.cyan().bold());
println!();
for layer_idx in 0..=max_layer {
let layer_tasks: Vec<&StaticDagTask> =
tasks.iter().filter(|t| t.layer == layer_idx).collect();
let line: Vec<String> = layer_tasks
.iter()
.map(|t| format!("{} {}", icons::verb_plain(&t.verb), t.id))
.collect();
println!(" {}", line.join(" "));
if layer_idx < max_layer {
let has_outgoing: Vec<bool> = layer_tasks
.iter()
.map(|t| edges.iter().any(|e| e.from == t.id))
.collect();
if has_outgoing.iter().any(|&b| b) {
let mut pipe_line = String::from(" ");
let mut arrow_line = String::from(" ");
for (i, task) in layer_tasks.iter().enumerate() {
let task_label_len = task.id.len() + 2; let center = task_label_len / 2;
if has_outgoing[i] {
pipe_line.push_str(&" ".repeat(center));
pipe_line.push_str(&format!("{}", "\u{2502}".dimmed())); pipe_line.push_str(&" ".repeat(task_label_len.saturating_sub(center + 1)));
} else {
pipe_line.push_str(&" ".repeat(task_label_len));
}
if has_outgoing[i] {
arrow_line.push_str(&" ".repeat(center));
arrow_line.push_str(&format!("{}", "\u{25BE}".dimmed())); arrow_line.push_str(&" ".repeat(task_label_len.saturating_sub(center + 1)));
} else {
arrow_line.push_str(&" ".repeat(task_label_len));
}
if i < layer_tasks.len() - 1 {
pipe_line.push_str(" ");
arrow_line.push_str(" ");
}
}
println!("{}", pipe_line);
println!("{}", arrow_line);
}
}
}
println!();
}