"""
graph_view.py - Generiert interaktive Graph-Visualisierung (Cytoscape.js).
"""
import json
from pathlib import Path
from typing import Optional
from .store import EngramStore
_HTML_TEMPLATE = """
Second Brain Graph
🧠 Second Brain Graph
Knoten: Engramme (Farbe = Confidence)
Grün=hoch, Gelb=mittel, Rot=niedrig
Links: Verknüpfungen
Klicke für Details
"""
def _confidence_color(conf: float) -> str:
if conf >= 0.8:
return "#27ae60" # Green
elif conf >= 0.5:
return "#f39c12" # Yellow
else:
return "#e74c3c" # Red
def _node_size(access_count: int) -> float:
return max(20, min(60, 20 + access_count * 5))
def generate_graph_html(store: EngramStore, output_path: str) -> str:
"""Generiert interaktive HTML-Graph-Visualisierung."""
engrams = store.get_all()
nodes = []
edges = []
node_ids = set()
for eg in engrams:
eid = str(eg.id)
conf = eg.compute_confidence()
color = _confidence_color(conf)
size = _node_size(eg.metadata.get("access_count", 0))
tags = ", ".join(eg.metadata.get("tags", []))
nodes.append({
"data": {
"id": eid,
"label": eg.content[:40] + ("..." if len(eg.content) > 40 else ""),
"title": eg.content,
"color": color,
"size": size,
"confidence": conf,
"confirmed": eg.correctness.confirmed,
"source": eg.metadata.get("source", "?"),
"tags": tags,
}
})
node_ids.add(eid)
for lid in eg.links:
lid_s = str(lid)
if lid_s in node_ids:
edges.append({
"data": {
"id": f"{eid}_{lid_s}",
"source": eid,
"target": lid_s,
}
})
elements = {"nodes": nodes, "edges": edges}
html = _HTML_TEMPLATE.format(elements_json=json.dumps(elements, ensure_ascii=False))
out = Path(output_path)
out.parent.mkdir(parents=True, exist_ok=True)
with open(out, "w", encoding="utf-8") as f:
f.write(html)
return str(out)