78 lines
3.3 KiB
EmacsLisp
78 lines
3.3 KiB
EmacsLisp
// node.el — Node type definitions and color/radius mapping.
|
||
//
|
||
// Node types mirror the Engram knowledge graph node_type field.
|
||
// Colors are chosen for dark-background (Studio) legibility.
|
||
|
||
// ── Node type constants ──────────────────────────────────────────────────────
|
||
|
||
fn node_type_memory() -> String { "Memory" }
|
||
fn node_type_backlog() -> String { "BacklogItem" }
|
||
fn node_type_knowledge() -> String { "Knowledge" }
|
||
fn node_type_entity() -> String { "Entity" }
|
||
fn node_type_default() -> String { "Node" }
|
||
|
||
// ── Color map ────────────────────────────────────────────────────────────────
|
||
|
||
fn node_color(node_type: String) -> String {
|
||
if str_eq(node_type, "Memory") { return "#58A6FF" }
|
||
if str_eq(node_type, "BacklogItem") { return "#C9A84C" }
|
||
if str_eq(node_type, "Knowledge") { return "#2ecc71" }
|
||
if str_eq(node_type, "Entity") { return "#e74c3c" }
|
||
if str_eq(node_type, "WorkContext") { return "#9b59b6" }
|
||
if str_eq(node_type, "Artifact") { return "#1abc9c" }
|
||
if str_eq(node_type, "Process") { return "#e67e22" }
|
||
"#7a8ba8"
|
||
}
|
||
|
||
// ── Radius ───────────────────────────────────────────────────────────────────
|
||
//
|
||
// Clamp salience (0.0–1.0) to radius range [6, 18].
|
||
|
||
fn node_radius(salience: Float) -> Float {
|
||
let min_r: Float = int_to_float(6)
|
||
let max_r: Float = int_to_float(18)
|
||
let range: Float = max_r - min_r
|
||
let clamped: Float = if salience < int_to_float(0) { int_to_float(0) } else { if salience > int_to_float(1) { int_to_float(1) } else { salience } }
|
||
min_r + range * clamped
|
||
}
|
||
|
||
fn node_radius_int(salience: Float) -> Int {
|
||
float_to_int(node_radius(salience))
|
||
}
|
||
|
||
// ── Label truncation ─────────────────────────────────────────────────────────
|
||
|
||
fn node_label_truncate(label: String) -> String {
|
||
let max_len: Int = 30
|
||
let l: Int = str_len(label)
|
||
if l <= max_len { return label }
|
||
str_slice(label, 0, max_len) + "..."
|
||
}
|
||
|
||
// ── Node JSON accessors ──────────────────────────────────────────────────────
|
||
//
|
||
// Nodes are passed as JSON objects: { id, label, node_type, salience, ... }
|
||
|
||
fn node_id(n_json: String) -> String {
|
||
json_get_string(n_json, "id")
|
||
}
|
||
|
||
fn node_label(n_json: String) -> String {
|
||
let lbl: String = json_get_string(n_json, "label")
|
||
if !str_eq(lbl, "") { return lbl }
|
||
// Fall back to first 40 chars of content
|
||
let c: String = json_get_string(n_json, "content")
|
||
if str_len(c) > 40 { return str_slice(c, 0, 40) }
|
||
c
|
||
}
|
||
|
||
fn node_type_field(n_json: String) -> String {
|
||
let t: String = json_get_string(n_json, "node_type")
|
||
if str_eq(t, "") { return node_type_default() }
|
||
t
|
||
}
|
||
|
||
fn node_salience(n_json: String) -> Float {
|
||
json_get_float(n_json, "salience")
|
||
}
|