import type { SimulationLinkDatum, SimulationNodeDatum } from "d3"; import type { TaskDescriptor, TasksFile } from "./task-loader"; import { createTaskMap } from "./task-loader"; export type TaskId = { id: string; task: TaskDescriptor; } & SimulationNodeDatum; function toMapById(nodes: TaskId[]): Map { let nodeMap = new Map(); for (let task of nodes) { if (task.id in nodeMap) throw 'duplicate IDs'; nodeMap.set(task.id, task); } return nodeMap; } function createNodes(tasks: TasksFile, old?: TaskId[]): TaskId[] { let m = (old == undefined) ? new Map() : toMapById(old); let res = tasks.tasks.map((t) => { return { id: t.id, task: t }; }); for (let t of res) { if (m.has(t.id)) { Object.assign(t, m.get(t.id)) } } return res; } export function createNodesAndEdges(tasks: TasksFile, oldNodes?: TaskId[], oldEdges?: SimulationLinkDatum[]): [TaskId[], SimulationLinkDatum[]] { let nodes = createNodes(tasks, oldNodes); // create mapping from ID to node let nodeMap = toMapById(nodes); let links: SimulationLinkDatum[] = []; for (const task of tasks.tasks) { const src = nodeMap.get(task.id)!; for (const id of task.requires) { const t = nodeMap.get(id); if (t === undefined) throw `missing task with id ${id}`; const l: SimulationLinkDatum = { source: src, target: t }; links.push(l); } } return [nodes, links]; }