//= require lib/_highcharts
|
|
var SerfSimulator = {
|
// Defaults
|
graphSettings: {
|
chart: {
|
type: 'spline'
|
},
|
title: {
|
text: null
|
},
|
xAxis: {
|
title: {
|
text: "Time (sec)",
|
style: {
|
color: "#B03C44",
|
},
|
}
|
},
|
yAxis: {
|
title: {
|
text: 'Convergence %',
|
style: {
|
color: "#B03C44",
|
},
|
},
|
min: 0.0,
|
max: 100.0
|
},
|
tooltip: {
|
formatter: function() {
|
return '<strong>'+ (Math.round(this.y*1000.0)/1000.0) +'%</strong><br/>'
|
}
|
},
|
legend: {
|
enabled: false
|
},
|
series: [
|
{
|
name: 'Convergence Rate',
|
data: [],
|
color: "#B03C44",
|
}
|
]
|
},
|
maxConverge: 0.9999,
|
interval: 0.2,
|
fanout : 3,
|
nodes: 30,
|
packetLoss: 0,
|
nodeFail: 0,
|
|
// init does all the stuff after the body is loaded
|
init: function() {
|
// Do not init if the graph is not present
|
if (!$("#graph").length) {
|
return
|
}
|
|
this.$graph = $("#graph");
|
this.$graph.highcharts(this.graphSettings);
|
this.$graphed = this.$graph.highcharts();
|
|
this.$interval = $("#interval");
|
this.$fanout = $("#fanout");
|
this.$nodes = $("#nodes");
|
this.$loss = $("#packetloss");
|
this.$failed = $("#failed");
|
this.$bytes = $("#bytes");
|
|
simulator = this;
|
|
// Draw initial
|
this.draw();
|
|
this.$interval.on("change", function() {
|
var interval = Number(this.value);
|
if (isNaN(interval) || interval <= 0) {
|
alert("Gossip interval must be a positive value!");
|
return;
|
}
|
simulator.interval = interval;
|
simulator.draw();
|
});
|
|
this.$fanout.on("change", function() {
|
var fanout = Number(this.value);
|
if (isNaN(fanout) || fanout <= 0) {
|
alert("Gossip fanout must be a positive value!");
|
return;
|
}
|
simulator.fanout = fanout;
|
simulator.draw();
|
});
|
|
this.$nodes.on("change", function() {
|
var nodes = Number(this.value);
|
if (isNaN(nodes) || nodes <= 1) {
|
alert("Must have at least one node!");
|
return;
|
}
|
simulator.nodes = nodes;
|
simulator.draw();
|
});
|
|
this.$loss.on("change", function() {
|
var pkt = Number(this.value);
|
if (isNaN(pkt) || pkt < 0 || pkt >= 100) {
|
alert("Packet loss must be greater or equal to 0 and less than 100");
|
return;
|
}
|
simulator.packetLoss = (pkt / 100.0);
|
simulator.draw();
|
});
|
|
this.$failed.on("change", function() {
|
var failed = Number(this.value);
|
if (isNaN(failed) || failed < 0 || failed >= 100) {
|
alert("Failure rate must be greater or equal to 0 and less than 100");
|
return;
|
}
|
simulator.nodeFail = (failed / 100.0);
|
simulator.draw();
|
});
|
},
|
|
draw: function() {
|
var data = this.seriesData();
|
this.$graphed.series[0].setData(data, false)/
|
this.$graphed.redraw();
|
|
var kilobits = this.bytesUsed() * 8;
|
var used = Math.round((kilobits / 1024) * 10) / 10;
|
this.$bytes.html("" + used);
|
},
|
|
convergenceAtRound: function(x) {
|
var contact = (this.fanout / this.nodes) * (1 - this.packetLoss) * (1 - this.nodeFail) * 0.5
|
var numInf = this.nodes / (1 + (this.nodes+1) * Math.pow(Math.E, -1*contact*this.nodes*x))
|
return numInf / this.nodes
|
},
|
|
roundLength: function() {
|
return this.interval
|
},
|
|
seriesData: function() {
|
var data = []
|
var lastVal = 0
|
var round = 0
|
var roundLength = this.roundLength()
|
while (lastVal < this.maxConverge && round < 100) {
|
lastVal = this.convergenceAtRound(round)
|
data.push([round * roundLength, lastVal*100.0])
|
round++
|
}
|
return data
|
},
|
|
bytesUsed: function() {
|
var roundLength = this.roundLength()
|
var roundsPerSec = 1 / roundLength
|
var packetSize = 1400
|
var send = packetSize * this.fanout * roundsPerSec
|
return send * 2
|
},
|
}
|
|
// Handle document ready function and the turbolinks load.
|
$(document).on("turbolinks:load", function() {
|
SerfSimulator.init()
|
});
|