class KeyGenerator { idx = 0; chars: string[] = []; constructor() { const chars = Array(26) .fill(1) .map((x, idx) => String.fromCharCode(97 + idx)); // 26 char this.chars = chars; } generateKey() { const key = this.chars[this.idx]; this.idx++; return key; } } // Classify nodes based on edge relationships export class Converter { keyGenerator; dict: Record = {}; // key is node id, value is combo constructor() { this.keyGenerator = new KeyGenerator(); } buildDict(edges: { source: string; target: string }[]) { edges.forEach((x) => { if (this.dict[x.source] && !this.dict[x.target]) { this.dict[x.target] = this.dict[x.source]; } else if (!this.dict[x.source] && this.dict[x.target]) { this.dict[x.source] = this.dict[x.target]; } else if (!this.dict[x.source] && !this.dict[x.target]) { this.dict[x.source] = this.dict[x.target] = this.keyGenerator.generateKey(); } }); return this.dict; } buildNodesAndCombos(nodes: any[], edges: any[]) { this.buildDict(edges); const nextNodes = nodes.map((x) => ({ ...x, combo: this.dict[x.id] })); const combos = Object.values(this.dict).reduce((pre, cur) => { if (pre.every((x) => x.id !== cur)) { pre.push({ id: cur, data: { label: `Combo ${cur}`, }, }); } return pre; }, []); return { nodes: nextNodes, combos }; } }