[ Launch: force-bubble-1 ] 3a9c506661877bd538c3 by jdutta
[ Launch: diagonal-test-1 ] e52929a90ea8b7a25bbd by jdutta
[ Launch: quick-chart-vert ] 2c8553335067321f44a4 by jdutta
[ Launch: quick-chart-1 ] 99181b7e0eb393be4380 by jdutta
[ Launch: scratchpad ] 9721189 by jdutta
-
-
Save jdutta/3a9c506661877bd538c3 to your computer and use it in GitHub Desktop.
network-share-sim
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{"description":"network-share-sim","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"s_action.csv":{"default":true,"vim":false,"emacs":false,"fontSize":12},"inlet.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"c_ip.csv":{"default":true,"vim":false,"emacs":false,"fontSize":12},"chart_data.csv":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"pingpong","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"ajax-caching":true,"thumbnail":"http://i.imgur.com/ELBizEx.gif"} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Testing of force graph without edges. | |
// Charge function idea from: http://vallandingham.me/bubble_charts_in_d3.html | |
// Multi-foci idea: http://bl.ocks.org/mbostock/1021841 | |
// Tip: for no overlap, use this: http://bl.ocks.org/mbostock/3231298 | |
// Configurable params | |
// Click on the number and see a magic slider appears to tweak it. | |
var config = { | |
width: 700, | |
height: 600, | |
nodeRadius: 3, | |
linkColor: '#ccc', | |
nodeColor: '#999', | |
toVisitNodeColor: '#ffbb42', | |
visitedNodeColor: '#ff3300' | |
}; | |
// [0, n) | |
function getRandInt(n) { | |
return Math.floor(Math.random() * n); | |
} | |
function generateNodes(n) { | |
var nodes = []; | |
for (var i=0; i<n; i++) { | |
nodes.push({ | |
id: i, | |
conn: [], | |
payload: {} | |
}); | |
} | |
return nodes; | |
} | |
function generateLinks(nodes, maxLinksPerNode) { | |
var links = []; | |
var n = nodes.length; | |
for (var i=0; i<n; i++) { | |
var node = nodes[i]; | |
if (node.conn.length < maxLinksPerNode) { | |
var numLinks = getRandInt(maxLinksPerNode-node.conn.length) + 1; | |
for (var j=0; j<numLinks; j++) { | |
var connNodeId = getRandInt(n); | |
while (connNodeId === node.id || node.conn.indexOf(connNodeId) > -1) { | |
connNodeId = getRandInt(n); | |
} | |
if (nodes[connNodeId].conn.length < maxLinksPerNode) { | |
node.conn.push(connNodeId); | |
nodes[connNodeId].conn.push(node.id); | |
links.push({ | |
source: node, | |
target: nodes[connNodeId] | |
}); | |
} | |
} | |
} | |
} | |
return links; | |
} | |
var nodes = generateNodes(100); | |
var links = generateLinks(nodes, 3); | |
var shareSim = shareSimulation(nodes); | |
d3.select("body").on("mousedown", shareSim.toggle); | |
visualize(nodes); | |
function visualize(nodes) { | |
var svg = d3.select('svg'); | |
var gRoot = svg.append('svg:g') | |
.attr('transform', 'translate(0, 50)'); | |
var node = gRoot.selectAll('.node'); | |
var link = gRoot.selectAll('.link'); | |
var line = d3.svg.line() | |
.x(function(d) { return d.x; }) | |
.y(function(d) { return d.y; }); | |
var force = d3.layout.force() | |
.nodes(nodes) | |
.links(links) | |
.size([config.width, config.height]) | |
.gravity(0.15) | |
.charge(function (d, i) { | |
return -100; | |
}) | |
.on('tick', tick) | |
.start(); | |
link = link.data(links) | |
.enter() | |
.append('svg:line') | |
.classed('link', true) | |
.style('stroke', config.linkColor) | |
.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 = node.data(nodes) | |
.data(nodes) | |
.enter() | |
.append('svg:g') | |
.attr('class', 'node') | |
.attr('transform', function (d) { return 'translate('+[d.x, d.y] +')'; }) | |
.call(force.drag) | |
node.append('svg:circle') | |
.attr('cx', 0) | |
.attr('cy', 0) | |
.attr('r', function (d) { | |
return config.nodeRadius; | |
}); | |
node.style('fill', function (d) { | |
if (!d.id) { | |
return config.visitedNodeColor; | |
} | |
return config.nodeColor; | |
}) | |
.style('stroke-width', 3); | |
function tick(e) { | |
if (e.alpha < 0.001) { | |
force.stop(); | |
return; | |
} | |
node.attr('transform', function (d) { return 'translate('+[d.x, d.y] +')'; }); | |
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; }); | |
} | |
function updateSimProgress(nodesToVisitNow, visitedNodes) { | |
console.log('update sim progress', nodesToVisitNow); | |
node.style('stroke', function (d) { | |
if (nodesToVisitNow[d.id]) { | |
return config.toVisitNodeColor; | |
} | |
}); | |
node.style('fill', function (d) { | |
if (visitedNodes[d.id]) { | |
return config.visitedNodeColor; | |
} | |
return config.nodeColor; | |
}); | |
link.style('stroke', function (d) { | |
if ((nodesToVisitNow[d.target.id] && visitedNodes[d.source.id]) || (nodesToVisitNow[d.source.id]) && visitedNodes[d.target.id]) { | |
return config.toVisitNodeColor; | |
} else if (visitedNodes[d.target.id] || visitedNodes[d.source.id]) { | |
return config.visitedNodeColor; | |
} | |
return config.linkColor; | |
}); | |
} | |
function resetSim() { | |
node.style('fill', function (d) { | |
if (!d.id) { | |
return config.visitedNodeColor; | |
} | |
return config.nodeColor; | |
}); | |
link.style('stroke', config.linkColor); | |
} | |
shareSim.addUpdateCallback(updateSimProgress); | |
shareSim.addResetCallback(resetSim); | |
} | |
function shareSimulation(nodes) { | |
var running = false; | |
var timer = null; | |
var updateCallbackFn = function () {}; | |
var resetCallbackFn = function () {}; | |
var visitedNodes = {}; | |
var nodesToVisitNow = {0: true}; | |
function oneStep() { | |
var toVisitNext = {}; | |
for (var nodeId in nodesToVisitNow) { | |
visitedNodes[nodeId] = true; | |
nodes[nodeId].conn.forEach(function (connNodeId) { | |
if (!visitedNodes[connNodeId] && !nodesToVisitNow[connNodeId] && !toVisitNext[connNodeId]) { | |
toVisitNext[connNodeId] = true; | |
} | |
}); | |
} | |
nodesToVisitNow = toVisitNext; | |
//console.log('to visit next', toVisitNext, visitedNodes); | |
} | |
function reset() { | |
visitedNodes = {}; | |
nodesToVisitNow = {0: true}; | |
} | |
// toggle function | |
return { | |
addUpdateCallback: function (fn) { | |
updateCallbackFn = fn; | |
}, | |
addResetCallback: function (fn) { | |
resetCallbackFn = fn; | |
}, | |
toggle: function() { | |
running = !running; | |
if (running) { | |
if (!Object.keys(nodesToVisitNow).length) { | |
reset(); | |
resetCallbackFn(); | |
} | |
timer = setInterval(function () { | |
oneStep(); | |
updateCallbackFn(nodesToVisitNow, visitedNodes); | |
if (!Object.keys(nodesToVisitNow).length) { | |
clearTimeout(timer); | |
} | |
}, 500); | |
} else { | |
clearTimeout(timer); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment