function draw(graph, state) {
let {time, visited_nodes, visited_edges, queue} = state;
let node_svg = ``, edge_svg = ``, queue_svg = ``, label_svg = ``;
for (let [name, v] of Object.entries(graph.nodes)) {
let c = (name in visited_nodes) ? "visited" : "";
node_svg += `<circle class="${c}" id="node-${name}" cx=${v.x} cy=${v.y} r=${nodeRadius} />\n`;
}
for (let {src,dst,length} of graph.edges) {
let c = (visited_edges.some(([s,d]) => (s == src && d == dst) || (s == dst && d == src)))
? "visited" : "";
let v = graph.nodes[src], u = graph.nodes[dst];
edge_svg += `<line class="${c}" x1=${v.x} y1=${v.y} x2=${u.x} y2=${u.y} />\n`;
let lx = (v.x + u.x)/2, ly = (v.y+u.y)/2;
let dx = v.x-u.x, dy = v.y-u.y;
let distance = Math.sqrt(dx*dx+dy*dy);
let ox = labelOffset*dy/distance, oy = -labelOffset*dx/distance;
label_svg += `<text x=${lx+ox} y=${ly+oy}>${length}</text>\n`;
}
for (let {src,dst,src_time,dst_time} of queue) {
if (time == src_time) continue;
let progress = (time - src_time)/(dst_time - src_time);
let v = graph.nodes[src], u = graph.nodes[dst];
let dx = u.x-v.x, dy = u.y-v.y;
let distance = Math.sqrt(dx*dx + dy*dy);
let vx = v.x + nodeRadius*dx/distance, vy = v.y + nodeRadius*dy/distance;
let ux = u.x - nodeRadius*dx/distance, uy = u.y - nodeRadius*dy/distance;
let x2 = vx + progress * (ux-vx), y2 = vy + progress * (uy-vy);
queue_svg += `<line x1=${v.x} y1=${v.y} x2="${x2}" y2="${y2}" />\n`
}
return svg`<svg viewBox="0 0 ${columns} ${rows}">
<g class=edges> ${edge_svg} <g class=in-progress> ${queue_svg} </g> </g>
<g class=nodes> ${node_svg} </g>
<g class=labels> ${label_svg} </g>
</svg>`
}