///TODO: Refactor this crap ///TODO: Add % of session and % of all time average lines to aggregate line graph var totalCan = $("#cycleBar"); var speedCan = $('#cycleSpeed'); var tflagCan = $('#tPostsByFlag'); var tflagPieCan = $('#tPostsByFlagPie'); var tNmaesCan = $('#tNmaes'); var tImagesCan = $('#tImages'); var tThreadsCan = $('#tThreads'); var tIdsCan= $('#tIds'); var tSubjectsCan = $('#tSubjects'); var tsflagCan = $('#tsPostsByFlag'); var tsflagPieCan = $('#tsPostsByFlagPie'); var tsNmaesCan = $('#tsNmaes'); var tsImagesCan = $('#tsImages'); var tsThreadsCan = $('#tsThreads'); var tsIdsCan= $('#tsIds'); var tsSubjectsCan = $('#tsSubjects'); var tsCycleSpeedCan = $('#tsCycleSpeed'); //var tsCycleAverageCan = $('#tsCycleAverage'); var tAgCandleCan = $('#tAgCandle'); var tAgLineCan =$('#tAgLine'); const maxEntries= client.preloadCycles; var cycleTableRollover = null; var sessionAverageRollover = null; function setStatus(str) { $('#status').text(str); } function _lerpRGB(a,b,t) { return { r: a.r + (b.r - a.r) * t, g: a.g + (b.g - a.g) * t, b: a.b + (b.b - a.b) * t }; } function lerpRGB(a,b,c,s,l) { var t = s/l; if(t<0.5) return _lerpRGB(a,b,t*2); else return _lerpRGB(b,c,(t-0.5)*2); } function add_new_candle(charts, data,update=true,close=null) { //charts.agcandle.data.labels.push(fixtime2(new Date(data.timestamp))); if(!data._candle.number.t) data._candle.number.t = new Date(data.timestamp); if(close!==null) data._candle.number.o = close; charts.agcandle.data.datasets[0].data.push(data._candle.number); if(update) charts.agcandle.update(); } function createNewCandle(charts, close) { if(!!charts.agcandle.data.datasets[0].data[charts.agcandle.data.datasets[0].data.length-1]) charts.agcandle.data.datasets[0].data[charts.agcandle.data.datasets[0].data.length-1].c = close; charts.agcandle.data.datasets[0].data.push({o: close, h:close, l:close, c:close, t:new Date()}); charts.agcandle.update(); } function createNewLinePoint(charts, data) { if(charts.agline.data.datasets[0].data[charts.agline.data.datasets[0].data.length-1]) { charts.agline.data.datasets[0].data[charts.agline.data.datasets[0].data.length-1] = data.number; charts.agline.data.datasets[1].data[charts.agline.data.datasets[0].data.length-1] = data.number/data._cycles; } charts.agline.data.labels.push(fixtime(new Date())); charts.agline.data.datasets[0].data.push(0); charts.agline.data.datasets[1].data.push(0); charts.agline.update(); } function total_add_data(chart, label, data, update=true){ //chart.addData(value, label); if(chart.data.labels.length>=maxEntries) { chart.data.labels.shift(); chart.data.datasets[0].data.shift(); chart.data.datasets[1].data.shift(); chart.data.datasets[2].data.shift(); chart.data.datasets[3].data.shift(); } chart.data.labels.push(label); chart.data.datasets[0].data.push(data.number); chart.data.datasets[1].data.push(data.names); chart.data.datasets[2].data.push(data.trips); chart.data.datasets[3].data.push(data.nametrips); if(update) chart.update(); } function fixtime(now){ var h= now.getHours(), m= now.getMinutes(), s= now.getSeconds(); return h+":"+m+":"+s; } function fixtime2(now){ var y = now.getFullYear(), M = now.getMonth(), d = now.getUTCDate(), h= now.getHours(), m= now.getMinutes(), s= now.getSeconds(); return y+"."+(M+1)+"."+d+" "+h+":"+m+":"+s; } function grapher(data, charts, update=true) { //cycle graph total_add_data(charts.total, fixtime(new Date(data.timestamp)), data,update); } function updateSection(gr, pfx, allTime, allTimeAverage,data=null) { var share = flagShare(allTime.number, allTime.countries); $('#'+pfx+'last').text(allTime.last); $('#'+pfx+'posts').text(allTime.number); $('#'+pfx+'flagshare').text(lcStr(flagShareStr(share),40)); $('#'+pfx+'avg').text(allTimeAverage.number.toFixed(2)); $('#'+pfx+'upcycle').text(allTimeAverage._n); $('#'+pfx+'flagshare_container > ul').empty(); share.sort(function (a, b) { return a.total < b.total ? 1 : -1; }); gr.aflag.data.labels.length = gr.aflag.data.datasets[0].data.length = 0; gr.aflagpie.data.labels.length = gr.aflagpie.data.datasets[0].data.length = gr.aflagpie.data.datasets[0].backgroundColor.length = 0; var cols = {r: 0, g: 0,b: 255}; var colm = {r: 0, g: 255, b: 0}; var cole = {r: 255, g: 0, b: 0}; var colstr = function(x) { return "rgba("+x.r+","+x.g+","+x.b+", 1.0)"; }; for(var i in share) { $('#'+pfx+'flagshare_container > ul').append("
  • "+share[i]["key"]+": "+(share[i]["val"]*100.00).toFixed(2)+"% ("+share[i]["total"]+")
  • "); gr.aflag.data.labels.push(share[i]["key"]); gr.aflag.data.datasets[0].data.push(share[i]["total"]); gr.aflagpie.data.labels.push(share[i]["key"]); gr.aflagpie.data.datasets[0].data.push(share[i]["total"]); gr.aflagpie.data.datasets[0].backgroundColor.push(colstr(lerpRGB(cols,colm,cole,i,share.length))); } gr.anamepie.data.datasets[0].data[0] = allTime.number-(allTime.names+allTime.trips+allTime.nametrips); gr.anamepie.data.datasets[0].data[1] = allTime.names; gr.anamepie.data.datasets[0].data[2] = allTime.trips; gr.anamepie.data.datasets[0].data[3] = allTime.nametrips; gr.aimagepie.data.datasets[0].data[0] = allTime.images; gr.aimagepie.data.datasets[0].data[1] = allTime.number-allTime.images; gr.athreadpie.data.datasets[0].data[0] = allTime.threads; gr.athreadpie.data.datasets[0].data[1] = allTime.number-allTime.threads; gr.aidspie.data.datasets[0].data[0] = allTime.ids; gr.aidspie.data.datasets[0].data[1] = allTime.number-allTime.ids; gr.asubjectspie.data.datasets[0].data[0] = allTime.subjects; gr.asubjectspie.data.datasets[0].data[1] = allTime.threads-allTime.subjects; gr.aflag.update(); gr.aflagpie.update(); gr.anamepie.update(); gr.aimagepie.update(); gr.athreadpie.update(); gr.aidspie.update(); gr.asubjectspie.update(); } function updateAllTime(gr,data=null) { updateSection(gr, "at_", client.allTime, client.allTimeAverage,data); } function flagShare(total, ctr) { var ret = []; for(var key in ctr) { ret.push({key: key, val: ctr[key]/total, total: ctr[key]}); } return ret; } function lcStr(str, mx) { if(str.length>mx) return str.slice(0, mx)+"..."; else return str; } function flagShareStr(share) { share.sort(function (a, b) { return a.total < b.total ? 1 : -1; }); var strs= []; for(var shr in share) { shr = share[shr]; strs.push(shr["key"]+": "+(shr["val"]*100.00).toFixed(2)+"%"); } return strs.join(", "); } //update session function graphCycle(data, charts,update=true) { $('#cytb > tbody > tr:first').before(""+ ""+fixtime(new Date(data.timestamp))+(!update?" (preload)":"")+""+ ""+data.last+""+ ""+data.number+""+ ""+((data.number/client.allTimeAverage.number)*100.00).toFixed(2)+"% "+(update&&(client.sessionAllTimeAverage.number>0)?(((data.number/client.sessionAllTimeAverage.number)*100.00).toFixed(2)+"% (session)"):"")+""+ ""+flagShareStr(flagShare(data.number, data.countries))+""+ ""+data.names+""+ ""+data.trips+""+ ""+data.nametrips+""+ ""); while( cycleTableRollover !== null && cycleTableRollover>0 && ($('#cytb > tbody').children().length)>cycleTableRollover) { $('#cytb > tbody > tr:last').remove(); } grapher(data, charts,update); updateSection(charts, "s_", client.sessionAllTime, client.sessionAllTimeAverage); //All time average comparison if(charts.speed.data.labels.length>=maxEntries){ charts.speed.data.labels.shift(); charts.speed.data.datasets[0].data.shift(); charts.speed.data.datasets[1].data.shift(); charts.speed.data.datasets[2].data.shift(); } charts.speed.data.labels.push(fixtime(new Date(data.timestamp))); charts.speed.data.datasets[0].data.push( ((data.number/client.allTimeAverage.number)*100.00).toFixed(2)); charts.speed.data.datasets[1].data.push( data.number); charts.speed.data.datasets[2].data.push( client.allTimeAverage.number); if(update) { charts.speed.update(); while(sessionAverageRollover!==null && sessionAverageRollover>0 && charts.aspeed.data.labels.length>sessionAverageRollover) { charts.aspeed.data.labels.shift(); charts.aspeed.data.datasets[0].data.shift(); charts.aspeed.data.datasets[1].data.shift(); charts.aspeed.data.datasets[2].data.shift(); } charts.aspeed.data.labels.push(fixtime(new Date(data.timestamp))); charts.aspeed.data.datasets[0].data.push( ((data.number/client.sessionAllTimeAverage.number)*100.00).toFixed(2)); charts.aspeed.data.datasets[1].data.push( data.number); charts.aspeed.data.datasets[2].data.push( client.sessionAllTimeAverage.number ); charts.aspeed.update(); } //Candle var lc = charts.agcandle.data.datasets[0].data[charts.agcandle.data.datasets[0].data.length-1]; if(lc) { lc.c = data.number; if(data.number>lc.h) lc.h = data.number; if(data.number0) charts.agline.data.datasets[1].data[charts.agline.data.datasets[0].data.length-1] = charts.agline.data.datasets[0].data[charts.agline.data.datasets[0].data.length-1] /client.superBuffer[client.superBuffer.length-1]._cycles; if(update) charts.agline.update(); } } function begin() { var chartASubjectsPie = new Chart(tSubjectsCan, { type: "pie", data: { labels: ["Subject OPs", "Other OPs"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartAIdsPie = new Chart(tIdsCan, { type: "pie", data: { labels: ["IDs", "Imptrash"], datasets: [{ label: "Share", backgroundColor:["blue", "grey"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartAthreadsPie = new Chart(tThreadsCan, { type: "pie", data: { labels: ["Threads", "Comments"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartAImagesPie = new Chart(tImagesCan, { type: "pie", data: { labels: ["Image posts", "Text posts"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartsANamesPie = new Chart(tNmaesCan, { type: "pie", data: { labels: ["Anons", "Namefags", "Tripfags", "Name+tripfags"], datasets: [{ label: "Share", backgroundColor:["blue", "green", "cyan", "red"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0,0,0] }] }, options: { //title: "Names", maintainAspectRatio: false, } }); var chartAFlagsPie = new Chart(tflagPieCan, { type: "pie", data: { labels: ["(unbound)"], datasets: [{ label: "Share", backgroundColor: ["blue","green","red"], //fillColor: ["blue", "green", "red"], borderColor: 'rgba(255,255,255, 0.75)', data: [1] }] }, options: { maintainAspectRatio: false, animation: false, legend: { display: false } } }); var chartAFlags = new Chart(tflagCan, { type: "bar", data: { labels: [], datasets: [{ label: "Posts", backgroundColor: "rgba(255, 124, 60, 0.8)", data: [], }] }, options: { maintainAspectRatio: false, animation: false, legend: { display: false }, scales: { yAxes: [{ ticks: { beginAtZero: true } }] } } }); /// START SESSION CHARTS var chartSSubjectsPie = new Chart(tsSubjectsCan, { type: "pie", data: { labels: ["Subject OPs", "Other OPs"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartSIdsPie = new Chart(tsIdsCan, { type: "pie", data: { labels: ["IDs", "Imptrash"], datasets: [{ label: "Share", backgroundColor:["blue", "grey"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartSthreadsPie = new Chart(tsThreadsCan, { type: "pie", data: { labels: ["Threads", "Comments"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartSImagesPie = new Chart(tsImagesCan, { type: "pie", data: { labels: ["Image posts", "Text posts"], datasets: [{ label: "Share", backgroundColor:["blue", "green"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0] }] }, options: { maintainAspectRatio: false, } }); var chartsSNamesPie = new Chart(tsNmaesCan, { type: "pie", data: { labels: ["Anons", "Namefags", "Tripfags", "Name+tripfags"], datasets: [{ label: "Share", backgroundColor:["blue", "green", "cyan", "red"], borderColor: 'rgba(255,255,255, 0.75)', data: [0,0,0,0] }] }, options: { //title: "Names", maintainAspectRatio: false, } }); var chartSFlagsPie = new Chart(tsflagPieCan, { type: "pie", data: { labels: ["(unbound)"], datasets: [{ label: "Share", backgroundColor: ["blue","green","red"], //fillColor: ["blue", "green", "red"], borderColor: 'rgba(255,255,255, 0.75)', data: [1] }] }, options: { maintainAspectRatio: false, animation: false, legend: { display: false } } }); var chartSFlags = new Chart(tsflagCan, { type: "bar", data: { labels: [], datasets: [{ label: "Posts", backgroundColor: "rgba(255, 124, 60, 0.8)", data: [], }] }, options: { maintainAspectRatio: false, animation: false, legend: { display: false }, scales: { yAxes: [{ ticks: { beginAtZero: true } }] } } }); var chartSCycleSpeed= new Chart(tsCycleSpeedCan, { type:"line", data: { labels: [], datasets: [{ label: "% of session avg", yAxisID: "A", borderColor: "rgba(0, 102, 204, 0.6)", backgroundColor: "rgb(0, 204, 255, 0.2)", tension: 0, data:[] }, { fill: false, yAxisID: "B", borderColor: "rgba(255,0,0,0.6)", label: "Number", tension: 0, data:[] }, { fill: false, yAxisID: "B", borderColor: "rgba(0,255,0,0.6)", label: "Average", tension: 0.1, data:[] }] }, options: { maintainAspectRatio: false, scales: { yAxes: [{ id: "A", ticks: { beginAtZero: true, callback: function(label, index, labels) { return label+"%"; } } }, { id: "B", ticks: { beginAtZero: true } }] } } }); /// END SESSION CHARTS var chartTotal = new Chart(totalCan, { type: "bar", data: { labels: Array(maxEntries).fill("(unbound)"), datasets: [{ label: "Posts", backgroundColor: "rgba(102, 255, 255, 0.6)", data: Array(maxEntries).fill(0) }, { label: "Namefags", backgroundColor: "rgba(102, 255, 102, 0.7)", data: Array(maxEntries).fill(0) }, { label: "Tripfags", backgroundColor: "rgba(204, 255, 102, 0.7)", data: Array(maxEntries).fill(0) }, { label: "Name+tripfags", backgroundColor: "rgba(255, 60, 12, 0.7)", data: Array(maxEntries).fill(0) }] }, options: { maintainAspectRatio: false, scales: { xAxes: [{ stacked: true }], yAxes: [{ ticks: { beginAtZero: true, callback: function (value) { if (Number.isInteger(value)) { return value; } } //stepSize: 1 } }] }, title: { display: true, text: 'Total posts per cycle' } } }); var chartSpeed = new Chart(speedCan, { type:"line", data: { labels: Array(maxEntries).fill("(unbound)"), datasets: [{ yAxisID: "A", borderColor: "rgba(0, 102, 204, 0.6)", backgroundColor: "rgb(0, 204, 255, 0.2)", label: "% of avg", tension: 0, data:Array(maxEntries).fill(0) }, { fill: false, yAxisID: "B", borderColor: "rgba(255,0,0,0.6)", label: "Number", tension: 0, data:Array(maxEntries).fill(0) }, { fill: false, yAxisID: "B", borderColor: "rgba(0,255,0,0.6)", label: "Average", tension: 0.1, data:Array(maxEntries).fill(0) }] }, options: { maintainAspectRatio: false, scales: { yAxes: [{ id: "A", ticks: { beginAtZero: true, callback: function(label, index, labels) { return label+"%"; } } }, { id: "B", ticks: { beginAtZero: true } }] } } }); //Aggregate stats var chartAGCandle = new Chart(tAgCandleCan, { type: "candlestick", data: { //labels: [], datasets: [{ label:"Number", data:[] }] }, options: { maintainAspectRatio: false, scales: { yAxes: [{ ticks: { beginAtZero: true } }] } } }); var chartAGLine = new Chart(tAgLine, { type: "line", data: { labels: [], datasets: [{ label:"Total posts", borderColor: "rgba(255,0,0,0.6)", fill: false, tension: 0, data:[] }, { label: "Average per cycle", borderColor: "rgba(0,255,0,0.6)", fill: false, tension: 0, data:[] }] }, options: { maintainAspectRatio: false } }); client.onWSclose = function() { setStatus("Dropped"); }; var g_globals = function(x) { x.total = chartTotal; x.speed = chartSpeed; x.agcandle = chartAGCandle; x.agline = chartAGLine; return x; }; var g_charts = function() { return g_globals({ aflag: chartAFlags, aflagpie: chartAFlagsPie, anamepie: chartsANamesPie, aimagepie: chartAImagesPie, athreadpie: chartAthreadsPie, aidspie: chartAIdsPie, asubjectspie: chartASubjectsPie }); }; var g_chartsSession = function() { return g_globals({ aflag: chartSFlags, aflagpie: chartSFlagsPie, anamepie: chartsSNamesPie, aimagepie: chartSImagesPie, athreadpie: chartSthreadsPie, aidspie: chartSIdsPie, asubjectspie: chartSSubjectsPie, aspeed: chartSCycleSpeed }); }; var g_chartsSuper = function() { return g_globals({ }); }; client.superGrapher = function(data) { //TODO: new supercycle //add_new_candle(g_chartsSuper(), data); createNewCandle(g_chartsSuper(), data._candle.number.c); createNewLinePoint(g_chartsSuper(), data); }; client.start(function(data) { //on message function updateAllTime(g_charts(),data); graphCycle(data, g_chartsSession()); }, function() { //init function $('#interval').text(client.info.interval+" ms"); $('#binterval').text(client.info.backendInterval+" s"); $('#pinterval').text((client.info.purgeInterval/1000/60).toFixed(2)+" m"); $('#spinterval').text((client.info.superPurgeInterval/1000/60/60).toFixed(2)+" h"); $('#board').text(client.info.board); $('#uptime').text(fixtime2(new Date(client.info.upSince))); $('#s_started').text(fixtime2(new Date())); //load superbuffer for(var i in client.superBuffer) { add_new_candle(g_chartsSuper(), client.superBuffer[i], false, (i>0?client.superBuffer[i-1]._candle.number.c:null)); chartAGLine.data.labels.push(fixtime(new Date(client.superBuffer[i].timestamp))); chartAGLine.data.datasets[0].data.push(client.superBuffer[i].number); chartAGLine.data.datasets[1].data.push(client.superBuffer[i].number/client.superBuffer[i]._cycles); } /*if(client.superBuffer.length<1) { add_new_candle(g_chartsSuper(), {_candle:{number:{o:0,c:0,h:0,l:0,t:new Date()}}}, false); }*/ //add last x from buffer for(var i in client.startupLast5) { graphCycle(client.startupLast5[i], g_charts(),false); } chartTotal.update(); chartSpeed.update(); chartAGCandle.update(); chartAGLine.update(); $('#at_flagshare_exp').on("click", function() { if($('#at_flagshare_container').is(":hidden")) { $('#at_flagshare_container').show(1000, function() { $('#at_flagshare_exp').text("-"); }); } else { $('#at_flagshare_container').hide(1000, function() { $('#at_flagshare_exp').text("+"); }); } }); $('#s_flagshare_exp').on("click", function() { if($('#s_flagshare_container').is(":hidden")) { $('#s_flagshare_container').show(1000, function() { $('#s_flagshare_exp').text("-"); }); } else { $('#s_flagshare_container').hide(1000, function() { $('#s_flagshare_exp').text("+"); }); } }); $('#cytb_purge').on("click", function() { $('#cytb_body').empty(); $('').appendTo($('#cytb_body')); }); $('#cytb_rlat').on('input', function() { var val = $('#cytb_rlat').val(); if(!isNaN(val)) { $('#e_rlat').text(""); cycleTableRollover = Number(val); } else { $('#e_rlat').text("Invalid number"); cycleTableRollover=null; } }); $('#cs_purge').on("click", function() { chartSCycleSpeed.data.datasets[0].data.length= chartSCycleSpeed.data.datasets[1].data.length= chartSCycleSpeed.data.datasets[2].data.length= chartSCycleSpeed.data.labels.length=0; chartSCycleSpeed.update(); }); $('#cs_rlat').on('input', function() { var val = $('#cs_rlat').val(); if(!isNaN(val)) { $('#e_cs_rlat').text(""); sessionAverageRollover = Number(val); } else { $('#e_cs_rlat').text("Invalid number"); sessionAverageRollover=null; } }); $('#ag_shift').on('click', function() { chartAGCandle.data.datasets[0].data.shift(); chartAGCandle.update(); chartAGLine.data.labels.shift(); chartAGLine.data.datasets[0].data.shift(); chartAGLine.update(); }); updateAllTime(g_charts()); setStatus("Synced"); }, function(err) { setStatus("Connection failed"); console.log("Error: "+err.toString()); client.stop(); }); }