function graph_settings() {
return {
chart: {
type: 'spline'
},
title: {
text: null
},
xAxis: {
title: {
text: "Time (sec)",
}
},
yAxis: {
title: {
text: 'Convergence %'
},
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: []
}]
}
}
function create_graph() {
$('#graph').highcharts(graph_settings())
return $('#graph').highcharts()
}
var Simulator = Class.$extend({
__init__ : function(graph, bytes, maxConverge) {
this.graph = graph
this.bytes = bytes
this.maxConverge = maxConverge
this.interval = 0.2
this.fanout = 3
this.nodes = 30
this.packetLoss = 0
this.nodeFail = 0
},
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
},
draw: function() {
var data = this.seriesData()
this.graph.series[0].setData(data, false)
this.graph.redraw()
var kilobits = this.bytesUsed() * 8
var used = Math.round((kilobits / 1024) * 10) / 10
this.bytes.html(""+used)
}
})
function update_interval(elem, simulator) {
var val = elem.value
var interval = Number(val)
if (isNaN(interval)) {
alert("Gossip interval must be a number!")
return
}
if (interval <= 0) {
alert("Gossip interval must be a positive value!")
return
}
simulator.interval = interval
simulator.draw()
console.log("Redraw with interval set to: " + interval)
}
function update_fanout(elem, simulator) {
var val = elem.value
var fanout = Number(val)
if (isNaN(fanout)) {
alert("Gossip fanout must be a number!")
return
}
if (fanout <= 0) {
alert("Gossip fanout must be a positive value!")
return
}
simulator.fanout = fanout
simulator.draw()
console.log("Redraw with fanout set to: " + fanout)
}
function update_nodes(elem, simulator) {
var val = elem.value
var nodes = Number(val)
if (isNaN(nodes)) {
alert("Node count must be a number!")
return
}
if (nodes <= 1) {
alert("Must have at least one node")
return
}
simulator.nodes = nodes
simulator.draw()
console.log("Redraw with nodes set to: " + nodes)
}
function update_packetloss(elem, simulator) {
var val = elem.value
var pkt = Number(val)
if (isNaN(pkt)) {
alert("Packet loss must be a number!")
return
}
if (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()
console.log("Redraw with packet loss set to: " + pkt)
}
function update_failed(elem, simulator) {
var val = elem.value
var failed = Number(val)
if (isNaN(failed)) {
alert("Failure rate must be a number!")
return
}
if (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()
console.log("Redraw with failure rate set to: " + failed)
}
// wait for dom ready
$(function(){
var bytes = $("#bytes")
var graph = create_graph()
var simulator = new Simulator(graph, bytes, 0.9999)
simulator.draw()
var interval = $("#interval")
interval.change(function() { update_interval(interval[0], simulator) })
var fanout = $("#fanout")
fanout.change(function() { update_fanout(fanout[0], simulator) })
var nodes = $("#nodes")
nodes.change(function() { update_nodes(nodes[0], simulator) })
var loss = $("#packetloss")
loss.change(function() { update_packetloss(loss[0], simulator) })
var failed = $("#failed")
failed.change(function() { update_failed(failed[0], simulator) })
})