export class Vertex { constructor(id, data) { this.id = id; this.data = data; this.edges = { from: [], to: [], }; } getEdges(label, away) { return this.edges[away ? 'from' : 'to'].filter( (edge) => edge.label === label, ); } } export class Edge { constructor(label, from, to, weight) { this.from = from; this.to = to; this.label = label; this.weight = weight; } } export class WDAG { constructor(scene) { this.scene = scene; this.vertices = new Map(); this.edgeLabels = new Map(); this.nextVertexId = 0; this.flowchart = scene?.flowchart ?? null; } withFlowchart() { this.scene.withAdditionalFlowchart(); this.flowchart = this.scene.lastFlowchart(); return this; } addVertex(id, data, label) { // Support simple case of auto-incremented numeric ids if (typeof id === 'object') { data = id; id = this.nextVertexId++; } if (this.vertices.has(id)) { throw new Error(`Vertex already exists with id: ${id}`); } const vertex = new Vertex(id, data); this.vertices.set(id, vertex); this.flowchart?.log(`${id}[${label ?? id}]`); return this; } setVertexLabel(id, label) { this.flowchart?.log(`${id}[${label}]`); } getVertex(id) { return this.vertices.get(id); } getVertexData(id) { return this.getVertex(id)?.data; } getVerticesData() { return Array.from(this.vertices.values()).map(({ data }) => data); } static getEdgeKey({ from, to }) { return btoa([from.id, to.id]).replaceAll(/[^A-Z]+/g, ''); } getEdge(label, from, to) { from = from instanceof Vertex ? from : this.getVertex(from); to = to instanceof Vertex ? to : this.getVertex(to); if (!from || !to) { return undefined; } const edges = this.edgeLabels.get(label); const edgeKey = WDAG.getEdgeKey({ from, to }); return edges?.get(edgeKey); } getEdgeWeight(label, from, to) { return this.getEdge(label, from, to)?.weight; } getEdgeHtml({ from, to }) { let html = '
${label} | ${weight} |