//= 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 ''+ (Math.round(this.y*1000.0)/1000.0) +'%
' } }, 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() });