feat(demo): use beautiful-mermaid for pipeline visualization

- Add beautiful-mermaid library (single-file ASCII renderer)
- Update pipeline_viz to generate mermaid graphs and render with beautiful-mermaid
- Creates dimensional network visualization with arrows connecting nodes
- Animates through effects and highlights active camera mode
This commit is contained in:
2026-03-16 02:12:03 -07:00
parent a1dcceac47
commit 996ba14b1d
3 changed files with 4219 additions and 102 deletions

View File

@@ -572,7 +572,7 @@ def run_pipeline_demo():
get_registry, get_registry,
set_monitor, set_monitor,
) )
from engine.pipeline_viz import generate_animated_pipeline from engine.pipeline_viz import generate_network_pipeline
print(" \033[1;38;5;46mMAINLINE PIPELINE DEMO\033[0m") print(" \033[1;38;5;46mMAINLINE PIPELINE DEMO\033[0m")
print(" \033[38;5;245mInitializing...\033[0m") print(" \033[38;5;245mInitializing...\033[0m")
@@ -667,7 +667,7 @@ def run_pipeline_demo():
camera.update(config.FRAME_DT) camera.update(config.FRAME_DT)
buf = generate_animated_pipeline(w, frame_number) buf = generate_network_pipeline(w, h, frame_number)
ctx = EffectContext( ctx = EffectContext(
terminal_width=w, terminal_width=w,

4107
engine/beautiful_mermaid.py Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,123 +1,133 @@
""" """
Pipeline visualization - ASCII text graphics showing the render pipeline. Pipeline visualization - Uses beautiful-mermaid to render the pipeline as ASCII network.
""" """
def generate_pipeline_visualization(width: int = 80, height: int = 24) -> list[str]: def generate_mermaid_graph(frame: int = 0) -> str:
"""Generate ASCII visualization of the pipeline. """Generate Mermaid flowchart for the pipeline."""
effects = ["NOISE", "FADE", "GLITCH", "FIREHOSE"]
active_effect = effects[(frame // 10) % 4]
Args: cam_modes = ["VERTICAL", "HORIZONTAL", "OMNI", "FLOATING"]
width: Width of the visualization in characters active_cam = cam_modes[(frame // 40) % 4]
height: Height in lines
Returns: return f"""graph LR
List of formatted strings representing the pipeline subgraph SOURCES
""" RSS[RSS Feeds]
lines = [] Poetry[Poetry DB]
Ntfy[Ntfy Msg]
Mic[Microphone]
end
for y in range(height): subgraph FETCH
line = "" Fetch(fetch_all)
Cache[(Cache)]
end
if y == 1: subgraph SCROLL
line = "" + "" * (width - 2) + "" Scroll(StreamController)
elif y == 2: Camera({active_cam})
line = "" + " RENDER PIPELINE ".center(width - 2) + "" end
elif y == 3:
line = "" + "" * (width - 2) + ""
elif y == 5: subgraph EFFECTS
line = "║ SOURCES ══════════════> FETCH ═════════> SCROLL ═══> EFFECTS ═> DISPLAY" Noise[NOISE]
elif y == 6: Fade[FADE]
line = "║ │ │ │ │" Glitch[GLITCH]
elif y == 7: Fire[FIREHOSE]
line = "║ RSS Poetry Camera Terminal" Hud[HUD]
elif y == 8: end
line = "║ Ntfy Cache Noise WebSocket"
elif y == 9:
line = "║ Mic Fade Pygame"
elif y == 10:
line = "║ Glitch Sixel"
elif y == 11:
line = "║ Firehose Kitty"
elif y == 12:
line = "║ Hud"
elif y == 14: subgraph DISPLAY
line = "" + "" * (width - 2) + "" Term[Terminal]
elif y == 15: Web[WebSocket]
line = "║ CAMERA MODES " Pygame[PyGame]
remaining = width - len(line) - 1 Sixel[Sixel]
line += ( end
"" * (remaining // 2 - 7)
+ " VERTICAL "
+ "" * (remaining // 2 - 6)
+ ""
)
elif y == 16:
line = (
""
+ "".center(8)
+ " "
+ "".center(8)
+ " "
+ "".center(8)
+ " "
+ "".center(8)
+ " " * 20
+ ""
)
elif y == 17:
line = (
"║ scroll up scroll left diagonal bobbing "
+ " " * 16
+ ""
)
elif y == 19: RSS --> Fetch
line = "" + "" * (width - 2) + "" Poetry --> Fetch
elif y == 20: Fetch --> Cache
fps = "60" Cache --> Scroll
line = ( Scroll --> Noise
f"║ FPS: {fps} │ Frame: 16.7ms │ Effects: 5 active │ Camera: VERTICAL " Scroll --> Fade
+ " " * (width - len(line) - 2) Scroll --> Glitch
+ "" Scroll --> Fire
) Scroll --> Hud
elif y == 21: Noise --> Term
line = "" + "" * (width - 2) + "" Fade --> Term
Glitch --> Term
Fire --> Term
Hud --> Term
else: Noise --> Web
line = " " * width Fade --> Web
Glitch --> Web
Fire --> Web
Hud --> Web
lines.append(line) Noise --> Pygame
Fade --> Pygame
Glitch --> Pygame
Fire --> Pygame
Hud --> Pygame
return lines Noise --> Sixel
Fade --> Sixel
Glitch --> Sixel
Fire --> Sixel
Hud --> Sixel
style {active_effect} fill:#90EE90
style Camera fill:#87CEEB
"""
def generate_animated_pipeline(width: int = 80, frame: int = 0) -> list[str]: def generate_network_pipeline(
"""Generate animated ASCII visualization. width: int = 80, height: int = 24, frame: int = 0
) -> list[str]:
"""Generate dimensional ASCII network visualization using beautiful-mermaid."""
try:
from engine.beautiful_mermaid import render_mermaid_ascii
Args: mermaid_graph = generate_mermaid_graph(frame)
width: Width of the visualization ascii_output = render_mermaid_ascii(mermaid_graph, padding_x=3, padding_y=2)
frame: Animation frame number
Returns: lines = ascii_output.split("\n")
List of formatted strings
"""
lines = generate_pipeline_visualization(width, 20)
anim_chars = ["", "", "", " ", "", "", ""] result = []
char = anim_chars[frame % len(anim_chars)] for y in range(height):
if y < len(lines):
line = lines[y]
if len(line) < width:
line = line + " " * (width - len(line))
elif len(line) > width:
line = line[:width]
result.append(line)
else:
result.append(" " * width)
for i, line in enumerate(lines): status_y = height - 2
if "Effects" in line: if status_y < height:
lines[i] = line.replace("" * 5, char * 5) fps = 60 - (frame % 15)
frame_time = 16.6 + (frame % 5) * 0.1
cam_modes = ["VERTICAL", "HORIZONTAL", "OMNI", "FLOATING"]
cam = cam_modes[(frame // 40) % 4]
effects = ["NOISE", "FADE", "GLITCH", "FIREHOSE"]
eff = effects[(frame // 10) % 4]
if "FPS:" in line: anim = "▓▒░ "[frame % 4]
lines[i] = ( status = f" FPS:{fps:3.0f} │ Frame:{frame_time:4.1f}ms │ {anim} {eff} │ Camera:{cam}"
f"║ FPS: {60 - frame % 10} │ Frame: {16 + frame % 5:.1f}ms │ Effects: {5 - (frame % 3)} active │ Camera: {['VERTICAL', 'HORIZONTAL', 'OMNI', 'FLOATING'][frame % 4]} " status = status[: width - 4].ljust(width - 4)
+ " " * (80 - len(lines[i]) - 2) result[status_y] = " " + status + ""
+ ""
)
return lines if height > 0:
result[0] = "" * width
result[height - 1] = "" * width
return result
except Exception as e:
return [
f"Error: {e}" + " " * (width - len(f"Error: {e}")) for _ in range(height)
]