syndicate-2017/tonyg-dissertation/html/conversation-animation.js

138 lines
4.5 KiB
JavaScript

var svg = d3.select("svg#conversation-animation"),
width = +svg.attr("width"),
height = +svg.attr("height");
var color = d3.scaleOrdinal(d3.schemeCategory20);
var simulation = d3.forceSimulation()
.force("link", d3.forceLink()
.distance(function(d) { return 200 / d.value; })
.id(function(d) { return d.id; }))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(0, 0))
.on("tick", function () {
link
.attr("x1", function(d) { return d.source.x; })
.attr("y1", function(d) { return d.source.y; })
.attr("x2", function(d) { return d.target.x; })
.attr("y2", function(d) { return d.target.y; });
node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
});
function obs(x) { return "(observe " + x + ")"; }
function entry(n,a) { return "(dns-entry " + n + " " + a + ")"; }
function laterThan(t) { return "(laterThan " + t + ")"; }
function mkProcess(n,c) { return {type: 'process', id: n, color: c}; }
function mkAssertion(n) { return {type: 'assertion', id: n}; }
function mkLink(s,t,v) { return {source: s, target: t, value: v || 1}; }
var matchWeight = 10;
var graph = {
nodes: [
mkProcess("Timer", "#FFC080"),
mkProcess("Cache", "#C0C0FF"),
mkProcess("Server", "#F0FFC0"),
mkAssertion(obs(obs(entry("*","*")))),
mkAssertion(obs(obs(laterThan("*"))))
],
links: [
mkLink("Timer", obs(obs(laterThan("*")))),
mkLink("Cache", obs(obs(entry("*","*")))),
mkLink("Server", obs(obs(entry("*","*")))),
]
};
var clientCounter = 1;
function clickHandler() {
var currentCounter = clientCounter;
clientCounter++;
var c = "Client" + currentCounter;
var n = "name" + currentCounter;
graph.nodes.push(mkProcess(c, "#FFC0C0"));
graph.nodes.push(mkAssertion(entry(n,"127.0.0."+currentCounter)));
graph.nodes.push(mkAssertion(obs(entry(n,"*"))));
graph.nodes.push(mkAssertion(obs(laterThan(currentCounter))));
graph.links.push(mkLink("Cache", obs(entry(n,"*"))));
graph.links.push(mkLink("Server", entry(n,"127.0.0."+currentCounter)));
graph.links.push(mkLink(c, obs(entry(n,"*"))));
graph.links.push(mkLink("Cache", obs(laterThan(currentCounter))));
graph.links.push(mkLink(entry(n,"127.0.0."+currentCounter), obs(entry(n,"*")), matchWeight));
graph.links.push(mkLink(obs(entry(n,"*")), obs(obs(entry("*","*"))), matchWeight));
graph.links.push(mkLink(obs(laterThan(currentCounter)), obs(obs(laterThan("*"))), matchWeight));
setTimeout(function () {
graph.nodes.splice(graph.nodes.findIndex(function (n) { return n.id === c; }), 1);
graph.links.splice(graph.links.findIndex(function (l) { return l.source.id === c; }), 1);
setupGraph();
}, 3000);
setupGraph();
}
svg.on("click", clickHandler);
svg.on("doubleclick", clickHandler);
var g = svg.append("g").attr("transform", "translate(" + width / 2 + "," + height / 2 + ")"),
link = g.append("g").attr("stroke", "#000").attr("stroke-width", 1.5).selectAll(".link"),
node = g.append("g").attr("stroke", "#fff").attr("stroke-width", 1.5).selectAll(".node");
function setupGraph() {
node = node.data(graph.nodes, function(d) { return d.id;});
node.exit().remove();
var group = node.enter().append("g")
.attr("class", function(d) { return d.type; })
.call(d3.drag()
.on("start", dragstarted)
.on("drag", dragged)
.on("end", dragended));
group.append("circle")
.attr("r", function(d) { return d.type === "process" ? 60 : 5 })
.attr("fill", function(d) { return d.color || "red"; })
group.append("text")
.attr("stroke", "none")
.attr("text-anchor", function(d) { return d.type === "process" ? "middle" : "start"; })
.attr("dx", function(d) { return d.type === "process" ? 0 : 12 })
.attr("dy", ".35em")
.text(function(d) { return d.id; });
node = group.merge(node);
link = link.data(graph.links, function(d) { return d.source.id + "-" + d.target.id; });
link.exit().remove();
link = link.enter().append("line")
.attr("stroke-width", function(d) { return Math.sqrt(d.value); })
.merge(link);
// Update and restart the simulation.
simulation.nodes(graph.nodes);
simulation.force("link").links(graph.links);
simulation.alpha(1).restart();
}
function dragstarted(d) {
if (!d3.event.active) simulation.alphaTarget(0.3).restart();
d.fx = d.x;
d.fy = d.y;
}
function dragged(d) {
d.fx = d3.event.x;
d.fy = d3.event.y;
}
function dragended(d) {
if (!d3.event.active) simulation.alphaTarget(0);
d.fx = null;
d.fy = null;
}
setupGraph();