fcn-wrtc
Version:
Fully Connected Network over WebRTC connection
233 lines (191 loc) • 5.72 kB
JavaScript
;
localStorage.debug = 'neighborhood-wrtc,fcn-wrtc'
const FCN = require('fcn-wrtc').Fcn;
const uuid = require('fcn-wrtc').uuid;
const id = uuid();
let o = [];
const max = 5;
let IS = [];
for(let i = 0; i < max; ++i) {
const options = {
webrtc: {
trickle: true,
iceServers : IS
},
room:'fcn-wrtc-example-'+id,
signalingAdress: 'https://signaling.herokuapp.com/',
verbose:true
};
o[i] = new FCN(options);
}
const connection = (time2wait = 1000) => {
for(let j = 1; j < max; ++j) {
o[j].connection(o[0]);
o[0].connection(o[j]);
}
};
const neigh = () => {
console.log('My id: ', p.getInviewId());
o.forEach(p => console.log(p.getNeighbours()));
};
const peers = () => {
o.forEach(p => {
console.log('My ids: i:', p.getInviewId(), ' o: ', p.getOutviewId());
console.log(p.getPeers());
});
};
const addPeer = () => {
const options = {
webrtc: {
trickle: true,
iceServers : IS
},
room:'fcn-wrtc-example-'+id,
signalingAdress: 'https://signaling.herokuapp.com/',
verbose:true
};
let fcn = new FCN(options);
fcn.connection(o[0]).then(s => {
console.log('New peer connected.');
o.push(fcn);
// wait two seconds for a proper connection establishment
setTimeout(() => { drawRps(); }, 2000);
});
}
// ======================================================================================================================
// ================================================== GRAPH CONSTRUCTION ================================================
// ======================================================================================================================
const d3 = window.d3;
let linkRps, nodeRps, textRps;
let svgRps;
let colorRps = d3.scale.category20();
let userColorRps = [];
const constructRpsGraph = () => {
let result = [];
let i = 0;
o.forEach(over => {
userColorRps[over.getOutviewId()+'$'+over.getInviewId()] = {
color: colorRps(i),
description: ` O-ID:${over.getOutviewId()} #i:${over.getPeers().i.length} | #o:${over.getPeers().o.length} `
};
userColorRps[over.getOutviewId()] = over.getInviewId();
userColorRps[over.getInviewId()] = over.getOutviewId();
i++;
});
o.forEach(over => {
if(over.getPeers().o.length === 0) {
result.push({
source: over.getOutviewId()+'$'+over.getInviewId(),
target: over.getOutviewId()+'$'+over.getInviewId(),
data: {
colorLink: '#FF3737'
}
});
}
over.getPeers().o.forEach(p => {
result.push({
source: over.getOutviewId()+'$'+over.getInviewId(),
target: userColorRps[p]+'$'+p,
data: {
colorLink: '#FF3737'
}
});
});
});
return result;
};
const drawRpsGraph = () => {
let nodes = {};
let links = constructRpsGraph();
// Compute the distinct nodes from the links.
links.forEach(function (link) {
link.source = nodes[link.source] || (nodes[link.source] = {name: link.source, data: link.data});
link.target = nodes[link.target] || (nodes[link.target] = {name: link.target, data: link.data});
});
let width = document.getElementById('graphRps').offsetWidth,
height = document.getElementById('graphRps').offsetHeight;
svgRps = d3.select('#graphRps').append('svg')
.attr('width', width)
.attr('height', height);
let force = d3.layout.force()
.nodes(d3.values(nodes))
.links(links)
.size([ width, height ])
.linkDistance(300)
.charge(-500)
.on('tick', tickRps)
.start();
// build the arrow.
svgRps.append('defs').selectAll('marker')
.data( [ 'endRps' ] ) // Different link/path types can be defined here
.enter().append('marker') // This section adds in the arrows
.attr('id', String).attr('viewBox', '0 -5 10 10').attr('refX', 15)
.attr('refY', -1.5).attr('markerWidth', 6).attr('markerHeight', 6)
.attr('orient', 'auto').append('path').attr('d', 'M0,-5L10,0L0,5');
linkRps = svgRps.append('g').selectAll('path')
.data(force.links())
.enter().append('path')
.attr('class', 'link').attr('marker-end', 'url(#endRps)')
.style('stroke', function (d) {
return d.data.colorLink;
})
.style('fill', 'none');
nodeRps = svgRps.append('g').selectAll('circle')
.data(force.nodes())
.enter().append('circle')
.attr('r', 6)
.style('fill', function (d) {
return userColorRps[d.name].color;
})
.on('mouseover', mouseover)
.on('mouseout', mouseout)
.call(force.drag);
textRps = svgRps.append('g').selectAll('text')
.data(force.nodes())
.enter().append('text')
.attr('x', 8)
.attr('y', '.31em')
.text(function (d) {
return userColorRps[d.name].description;
});
};
const drawRps = () => {
if(svgRps) svgRps.remove();
drawRpsGraph();
};
function linkArc (d) {
let dx = d.target.x - d.source.x, dy = d.target.y - d.source.y, dr = Math.sqrt(dx * dx + dy * dy) * 4;
return 'M' + d.source.x + ',' + d.source.y + 'A' + dr + ',' + dr + ' 0 0,1 ' + d.target.x + ',' + d.target.y;
}
function transform (d) {
return 'translate(' + d.x + ',' + d.y + ')';
}
function tickRps () {
linkRps.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;
});
linkRps.attr('d', linkArc);
nodeRps.attr('transform', transform);
textRps.attr('transform', transform);
}
function mouseoverOverlay () {
const d = d3.select(this).data()[0];
console.log('profile', userColorOverlay[d.name].profile );
console.log('views:', userColorOverlay[d.name].views);
}
function mouseover () {
d3.select(this).transition()
.duration(750)
.attr('r', 16);
}
function mouseout () {
d3.select(this).transition()
.duration(750)
.attr('r', 8);
}