UNPKG

scuttle-example

Version:

An example of demoing the scuttlebut protocol

196 lines (149 loc) 3.94 kB
module.exports = Demo var Gossip = require('../index') , d3 = require('d3') function Demo(n) { this.n = n this.keys = [] var nodes = [] , links = [] for(var i = 0; i < n; ++i) { this.keys[i] = 'id-' + i nodes[i] = {} nodes[i].gossip = Gossip(this.keys[i], 100, 10) nodes[i].gossip.on('state', this.update.bind(this)) } for(var i = 0; i < n; ++i) { var after = i ? i - 1 : n - 1 , before = i % (n - 1) links.push({ source: nodes[i] , target: nodes[after] }) links.push({ source: nodes[i] , target: nodes[before] }) nodes[i].gossip .pipe(nodes[after].gossip) .pipe(nodes[i].gossip) nodes[i].gossip .pipe(nodes[before].gossip) .pipe(nodes[i].gossip) } this.force = d3.layout.force() .nodes(nodes) .links(links) this.line = d3.svg.line.radial() } Demo.prototype.tick = function() { this.link .attr('d', linkArc) this.node.attr( 'transform' , translate ) function translate(d) { return 'translate(' + d.x + ',' + d.y + ')' } } Demo.prototype.dim = function() { this.height = this.canvas[0][0].clientHeight this.width = this.canvas[0][0].clientWidth if(!this.height || !this.width) { this.force.stop() return this.canvas[0][0].classList.add('browser-error') } this.force .size([this.width, this.height]) .linkDistance(100) .charge(-(this.width) || -1000) .gravity(0.2) } Demo.prototype.start = function() { // Establishing some constants var self = this self.canvas = d3.select('body') .insert('div', ':first-child') .attr('class', 'graph') .append('svg') d3.select('body').select('.graph') .append('h3') .attr('class', 'error-message') .text("For best viewing, check this out in opera or chrome.") self.dim() self.force .charge(-1000) .on('tick', this.tick.bind(this)) self.link = self.canvas.selectAll('.link') .data(self.force.links()) .enter() .append('path') .attr('class', 'link') self.node = self.canvas.selectAll('.node') .data(self.force.nodes()) .enter() .append('g') .attr('id', lookup('gossip.id')) .attr('transform', function(d, i) { return 'translate(' + (+self.width / 2) + ',' + (+self.height / 2) + ')' }) self.node.attr('class', 'node') .attr('fill', function(d, i) { return fill(i) }) .attr('stroke', function(d, i) { return fill(i) }) self.node.append('polygon') self.node.append('g') .append('text') .attr('x', 10) self.node.select('g') .append('text') .attr('x', -20) .attr('class', 'id') .text(lookup('gossip.id')) self.node.call(self.force.drag) self.update() } var fill = d3.scale.category10().domain(d3.range(10)) Demo.prototype.update = function() { var self = this self.node.select('polygon') .transition() .duration(300) .attr('points', self.points.bind(self)) self.node.select('text').text(lookup('gossip.version')) } Demo.prototype.points = function(data) { var step = 2 * Math.PI / this.n , points = [] , i = 0 while(i < this.n) { var val = data.gossip.get(this.keys[i]).value || 0 points[2 * i] = [(val + 1) * 10, i * step] points[(2 * i) + 1] = [1, (i + 0.5) * step] i += 1 } return this.line(points).slice(1).split('L').join(' ') } function linkArc(d) { var dy = d.target.y - d.source.y , dx = d.target.x - d.source.x var dr = Math.sqrt(dx * dx + dy * dy) return 'M' + d.source.x + ',' + d.source.y + 'A' + dr + ',' + dr + ' 0 0,1 ' + d.target.x + ',' + d.target.y } function lookup(str) { var keys = str.split('.') return function(obj) { for(var i = 0, len = keys.length; i < len; ++i) { if(obj === null || obj === undefined) { return } obj = obj[keys[i]] } return obj } }