';
if (!proc.active) phtml = '
';
phtml += "
Process " + i + ":
";
phtml += "
PID: " + (proc.pid||"None (not active)") + "
";
if (proc.threads && proc.active) {
phtml += "
Thread ID | Access count | Bytes served | Last Used | Last client | Last request |
";
for (var j in proc.threads) {
var thread = proc.threads[j];
thread.request = (thread.request||"(Unknown)").replace(/[<>]+/g, "");
phtml += ""+thread.thread+" | "+thread.count+" | "+thread.bytes+" | "+thread.last_used+" | "+thread.client+" | "+thread.request+" |
";
}
phtml += "
";
} else {
phtml += "
No thread information available
";
}
phtml += "
";
box.innerHTML += phtml;
}
}
function waitTwo() {
getAsync(location.href + "?view=json&rnd=" + Math.random(), null, refreshCharts)
}
function showPanel(what) {
var items = ['dashboard','misc','threads','modules'];
for (var i in items) {
var item = items[i];
var btn = document.getElementById(item+'_button');
var panel = document.getElementById(item+'_panel');
if (item == what) {
btn.setAttribute("class", "btn active");
panel.style.display = 'block';
} else {
btn.setAttribute("class", "btn");
panel.style.display = 'none';
}
}
// special constructors
if (what == 'threads') {
getAsync(location.href + "?view=json&extended=true&rnd=" + Math.random(), null, refreshThreads)
}
}
function fn(num) {
num = num + "";
num = num.replace(/(\d)(\d{9})$/, '$1,$2');
num = num.replace(/(\d)(\d{6})$/, '$1,$2');
num = num.replace(/(\d)(\d{3})$/, '$1,$2');
return num;
}
function fnmb(num) {
var add = "bytes";
var dec = "";
var mul = 1;
if (num > 1024) { add = "KB"; mul= 1024; }
if (num > (1024*1024)) { add = "MB"; mul= 1024*1024; }
if (num > (1024*1024*1024)) { add = "GB"; mul= 1024*1024*1024; }
if (num > (1024*1024*1024*1024)) { add = "TB"; mul= 1024*1024*1024*1024; }
num = num / mul;
if (add != "bytes") {
dec = "." + Math.floor( (num - Math.floor(num)) * 100 );
}
return ( fn(Math.floor(num)) + dec + " " + add );
}
function sort(a,b){
last_col = -1;
var sort_reverse = false;
var sortWay = a.getAttribute("sort_" + b);
if (sortWay && sortWay == "forward") {
a.setAttribute("sort_" + b, "reverse");
sort_reverse = true;
}
else {
a.setAttribute("sort_" + b, "forward");
}
var c,d,e,f,g,h,i;
c=a.rows.length;
if(c<1){ return; }
d=a.rows[1].cells.length;
e=1;
var j=new Array(c);
f=0;
for(h=e;h
n[b]) ? true : false;
var lt = (m[b] parseInt(n[b], 10) ? true : false; lt = parseInt(m[b], 10) < parseInt(n[b], 10) ? true : false; }
if (sort_reverse) {gt = (!gt); lt = (!lt);}
if(gt){
j[i+1]=m;
j[i]=n;
l=true;
}
}
else{
if(lt){
j[i+1]=m;
j[i]=n;
l=true;
}
}
}
if(l===false){
break;
}
}
f=e;
for(h=0;h 1024) { add = "KB"; mul= 1024; }
if (num > (1024*1024)) { add = "MB"; mul= 1024*1024; }
if (num > (1024*1024*1024)) { add = "GB"; mul= 1024*1024*1024; }
if (num > (1024*1024*1024*1024)) { add = "TB"; mul= 1024*1024*1024*1024; }
num = num / mul;
if (add != "b" && num < 10) {
dec = "." + Math.floor( (num - Math.floor(num)) * 100 );
}
return ( Math.floor(num) + dec + " " + add );
}
// Hue, Saturation and Lightness to Red, Green and Blue:
function quokka_internal_hsl2rgb (h,s,l)
{
var min, sv, switcher, fract, vsf;
h = h % 1;
if (s > 1) s = 1;
if (l > 1) l = 1;
var v = (l <= 0.5) ? (l * (1 + s)) : (l + s - l * s);
if (v === 0)
return { r: 0, g: 0, b: 0 };
min = 2 * l - v;
sv = (v - min) / v;
var sh = (6 * h) % 6;
switcher = Math.floor(sh);
fract = sh - switcher;
vsf = v * sv * fract;
switch (switcher)
{
case 0: return { r: v, g: min + vsf, b: min };
case 1: return { r: v - vsf, g: v, b: min };
case 2: return { r: min, g: v, b: min + vsf };
case 3: return { r: min, g: v - vsf, b: v };
case 4: return { r: min + vsf, g: min, b: v };
case 5: return { r: v, g: min, b: v - vsf };
}
return {r:0, g:0, b: 0};
}
// RGB to Hex conversion
function quokka_internal_rgb2hex(r, g, b) {
return "#" + ((1 << 24) + (Math.floor(r) << 16) + (Math.floor(g) << 8) + Math.floor(b)).toString(16).slice(1);
}
// Generate color list used for charts
var colors = [];
var rgbs = []
var numColorRows = 6;
var numColorColumns = 20;
for (var x=0;x 8 ? (Math.random()) : (rnd[0]/255), y > 8 ? (0.75+(y*0.05)) : (rnd[1]/255), y > 8 ? (0.42 + (y*0.05*(x/numColorRows))) : (0.1 + rnd[2]/512));
// Light (primary) color:
var hex = quokka_internal_rgb2hex(color.r*255, color.g*255, color.b*255);
// Darker variant for gradients:
var dhex = quokka_internal_rgb2hex(color.r*131, color.g*131, color.b*131);
// Medium variant for legends:
var mhex = quokka_internal_rgb2hex(color.r*200, color.g*200, color.b*200);
colors.push([hex, dhex, color, mhex]);
}
}
/* Function for drawing pie diagrams
* Example usage:
* quokkaCircle("canvasName", [ { title: 'ups', value: 30}, { title: 'downs', value: 70} ] );
*/
function quokkaCircle(id, tags, opts) {
// Get Canvas object and context
var canvas = document.getElementById(id);
var ctx=canvas.getContext("2d");
// Calculate the total value of the pie
var total = 0;
var k;
for (k in tags) {
tags[k].value = Math.abs(tags[k].value);
total += tags[k].value;
}
// Draw the empty pie
var begin = 0;
var stop = 0;
var radius = (canvas.height*0.75)/2;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.shadowBlur = 6;
ctx.shadowOffsetX = 6;
ctx.shadowOffsetY = 6;
ctx.shadowColor = "#555";
ctx.lineWidth = (opts && opts.hires) ? 6 : 2;
ctx.strokeStyle = "#222";
ctx.arc((canvas.width-140)/2,canvas.height/2,radius, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();
ctx.fill();
ctx.shadowBlur = 0;
ctx.shadowOffsetY = 0;
ctx.shadowOffsetX = 0;
// Draw a title if set:
if (opts && opts.title) {
ctx.font= (opts && opts.hires) ? "28px Sans-Serif" : "15px Sans-Serif";
ctx.fillStyle = "#000000";
ctx.textAlign = "center";
ctx.fillText(opts.title,(canvas.width-140)/2, (opts && opts.hires) ? 30:15);
ctx.textAlign = "left";
}
ctx.beginPath();
var posY = 50;
var left = 120 + ((canvas.width-140)/2) + ((opts && opts.hires) ? 40 : 25)
for (k in tags) {
var val = tags[k].value;
stop = stop + (2 * Math.PI * (val / total));
// Make a pizza slice
ctx.beginPath();
ctx.lineCap = 'round';
ctx.arc((canvas.width-140)/2,canvas.height/2,radius,begin,stop);
ctx.lineTo((canvas.width-140)/2,canvas.height/2);
ctx.closePath();
ctx.lineWidth = 0;
ctx.stroke();
// Add color gradient
var grd=ctx.createLinearGradient(0,canvas.height*0.2,0,canvas.height);
grd.addColorStop(0,colors[k % colors.length][1]);
grd.addColorStop(1,colors[k % colors.length][0]);
ctx.fillStyle = grd;
ctx.fill();
begin = stop;
// Make color legend
ctx.fillRect(left, posY-((opts && opts.hires) ? 15 : 10), (opts && opts.hires) ? 14 : 7, (opts && opts.hires) ? 14 : 7);
// Add legend text
ctx.shadowColor = "rgba(0,0,0,0)"
ctx.font= (opts && opts.hires) ? "22px Sans-Serif" : "12px Sans-Serif";
ctx.fillStyle = "#000";
ctx.fillText(tags[k].title + " (" + Math.floor(val) + (opts && opts.pct ? "%" : "") + ")",left+20,posY);
posY += (opts && opts.hires) ? 28 : 14;
}
}
/* Function for drawing line charts
* Example usage:
* quokkaLines("myCanvas", ['Line a', 'Line b', 'Line c'], [ [x1,a1,b1,c1], [x2,a2,b2,c2], [x3,a3,b3,c3] ], { stacked: true, curve: false, title: "Some title" } );
*/
function quokkaLines(id, titles, values, options, sums) {
var canvas = document.getElementById(id);
var ctx=canvas.getContext("2d");
// clear the canvas first
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.lineWidth = 0.25;
ctx.strokeStyle = "#000000";
var lwidth = 300;
var lheight = 75;
wspace = (options && options.hires) ? 110 : 55;
var rectwidth = canvas.width - lwidth - wspace;
var stack = options ? options.stack : false;
var curve = options ? options.curve : false;
var title = options ? options.title : null;
var spots = options ? options.points : false;
var noX = options ? options.nox : false;
var verts = options ? options.verts : true;
if (noX) {
lheight = 0;
}
// calc rectwidth if titles are large
var nlwidth = 0
for (var k in titles) {
ctx.font= (options && options.hires) ? "24px Sans-Serif" : "12px Sans-Serif";
ctx.fillStyle = "#00000";
var x = parseInt(k)
if (!noX) {
x = x + 1;
}
var sum = 0
for (var y in values) {
sum += values[y][x]
}
var t = titles[k] + (!options.nosum ? " (" + ((sums && sums[k]) ? sums[k] : sum.toFixed(0)) + ")" : "");
var w = ctx.measureText(t).width + 48;
if (w > lwidth && w > nlwidth) {
nlwidth = w
}
if (nlwidth > 0) {
rectwidth -= nlwidth - lwidth
lwidth = nlwidth
}
}
// Draw a border
ctx.lineWidth = 0.5;
ctx.strokeRect((wspace*0.75), 30, rectwidth, canvas.height - lheight - 40);
// Draw a title if set:
if (title != null) {
ctx.font= (options && options.hires) ? "24px Sans-Serif" : "15px Sans-Serif";
ctx.fillStyle = "#00000";
ctx.textAlign = "center";
ctx.fillText(title,rectwidth/2, 20);
}
// Draw legend
ctx.textAlign = "left";
var posY = 50;
for (var k in titles) {
var x = parseInt(k)
if (!noX) {
x = x + 1;
}
var sum = 0
for (var y in values) {
sum += values[y][x]
}
var title = titles[k] + (!options.nosum ? (" (" + ((sums && sums[k]) ? sums[k] : sum.toFixed(0)) + ")") : "");
if (options && options.lastsum) {
title = titles[k] + " (" + values[values.length-1][x].toFixed(0) + ")";
}
ctx.fillStyle = colors[k % colors.length][3];
ctx.fillRect(wspace + rectwidth + 75 , posY-((options && options.hires) ? 18:9), (options && options.hires) ? 20:10, (options && options.hires) ?20:10);
// Add legend text
ctx.font= (options && options.hires) ? "24px Sans-Serif" : "14px Sans-Serif";
ctx.fillStyle = "#00000";
ctx.fillText(title,canvas.width - lwidth + ((options && options.hires) ? 100:60), posY);
posY += (options && options.hires) ? 30:15;
}
// Find max and min
var max = null;
var min = 0;
var stacked = null;
for (x in values) {
var s = 0;
for (y in values[x]) {
if (y > 0 || noX) {
s += values[x][y];
if (max === null || max < values[x][y]) {
max = values[x][y];
}
if (min === null || min > values[x][y]) {
min = values[x][y];
}
}
}
if (stacked === null || stacked < s) {
stacked = s;
}
}
if (min == max) max++;
if (stack) {
min = 0;
max = stacked;
}
// Set number of lines to draw and each step
var numLines = 5;
var step = (max-min) / (numLines+1);
// Prettify the max value so steps aren't ugly numbers
if (step %1 != 0) {
step = (Math.round(step+0.5));
max = step * (numLines+1);
}
// Draw horizontal lines
for (x = -1; x <= numLines; x++) {
ctx.beginPath();
var y = 30 + (((canvas.height-40-lheight) / (numLines+1)) * (x+1));
ctx.moveTo(wspace*0.75, y);
ctx.lineTo(wspace*0.75 + rectwidth, y);
ctx.lineWidth = 0.25;
ctx.stroke();
// Add values
ctx.font= (options && options.hires) ? "20px Sans-Serif" : "12px Sans-Serif";
ctx.fillStyle = "#000000";
var val = Math.round( ((max-min) - (step*(x+1))) );
if (options && options.traffic) {
val = quokka_fnmb(val);
}
ctx.textAlign = "left";
ctx.fillText( val,canvas.width - lwidth - 20, y+8);
ctx.textAlign = "right";
ctx.fillText( val,wspace-32, y+8);
ctx.closePath();
}
// Draw vertical lines
var sx = 1
var numLines = values.length-1;
var step = (canvas.width - lwidth - wspace*0.75) / values.length;
while (step < 24) {
step *= 2
sx *= 2
}
if (verts) {
ctx.beginPath();
for (var x = 1; x < values.length; x++) {
if (x % sx == 0) {
var y = (wspace*0.75) + (step * (x/sx));
ctx.moveTo(y, 30);
ctx.lineTo(y, canvas.height - 10 - lheight);
ctx.lineWidth = 0.25;
ctx.stroke();
}
}
ctx.closePath();
}
// Some pre-calculations of steps
var step = (rectwidth) / (values.length > 1 ? values.length-1:1);
// Draw X values if noX isn't set:
if (noX != true) {
ctx.beginPath();
for (var i = 0; i < values.length; i++) {
zz = 1
var x = (wspace*0.75) + ((step) * i);
var y = canvas.height - lheight + 5;
if (i % sx == 0) {
ctx.translate(x, y);
ctx.moveTo(0,0);
ctx.lineTo(0,-15);
ctx.stroke();
ctx.rotate(45*Math.PI/180);
ctx.textAlign = "left";
var val = values[i][0];
if (val.constructor.toString().match("Date()")) {
val = val.toDateString();
}
ctx.fillText(val.toString(), 0, 0);
ctx.rotate(-45*Math.PI/180);
ctx.translate(-x,-y);
}
}
ctx.closePath();
}
// Draw each line
var stacks = [];
var pstacks = [];
for (k in values) { if (k > 0) { stacks[k] = 0; pstacks[k] = canvas.height - 40 - lheight; }}
for (k in titles) {
var maxY = 0, minY = 99999;
ctx.beginPath();
var color = colors[k % colors.length][0];
var f = parseInt(k) + 1;
if (noX) {
f = parseInt(k);
}
var value = values[0][f];
var step = rectwidth / numLines;
var x = (wspace*0.75);
var y = (canvas.height - 10 - lheight) - (((value-min) / (max-min)) * (canvas.height - 40 - lheight));
var py = y;
if (stack) {
stacks[0] = stacks[0] ? stacks[0] : 0
y -= stacks[0];
pstacks[0] = stacks[0];
stacks[0] += (((value-min) / (max-min)) * (canvas.height - 40 - lheight));
}
// Draw line
ctx.moveTo(x, y);
var pvalY = y;
var pvalX = x;
for (var i in values) {
if (i > 0) {
x = (wspace*0.75) + (step*i);
var f = parseInt(k) + 1;
if (noX == true) {
f = parseInt(k);
}
value = values[i][f];
y = (canvas.height - 10 - lheight) - (((value-min) / (max-min)) * (canvas.height - 40 - lheight));
if (stack) {
y -= stacks[i];
pstacks[i] = stacks[i];
stacks[i] += (((value-min) / (max-min)) * (canvas.height - 40- lheight));
}
if (y > maxY) maxY = y;
if (y < minY) minY = y;
// Draw curved lines??
/* We'll do: (x1,y1)-----(x1.5,y1)
* |
* (x1.5,y2)-----(x2,y2)
* with a quadratic beizer thingy
*/
if (curve) {
ctx.bezierCurveTo((pvalX + x) / 2, pvalY, (pvalX + x) / 2, y, x, y);
pvalX = x;
pvalY = y;
}
// Nope, just draw straight lines
else {
ctx.lineTo(x, y);
}
if (spots) {
ctx.fillStyle = color;
ctx.translate(x-2, y-2);
ctx.rotate(-45*Math.PI/180);
ctx.fillRect(-2,1,4,4);
ctx.rotate(45*Math.PI/180);
ctx.translate(-x+2, -y+2);
}
}
}
ctx.lineWidth = 4;
ctx.strokeStyle = color;
ctx.stroke();
if (minY == maxY) maxY++;
// Draw stack area
if (stack) {
ctx.globalAlpha = 0.65;
for (i in values) {
if (i > 0) {
var f = parseInt(k) + 1;
if (noX == true) {
f = parseInt(k);
}
x = (wspace*0.75) + (step*i);
value = values[i][f];
y = (canvas.height - 10 - lheight) - (((value-min) / (max-min)) * (canvas.height - 40 - lheight));
y -= stacks[i];
}
}
var pvalY = y;
var pvalX = x;
if (y > maxY) maxY = y;
if (y < minY) minY = y;
for (i in values) {
var l = values.length - i - 1;
x = (wspace*0.75) + (step*l);
y = canvas.height - 10 - lheight - pstacks[l];
if (y > maxY) maxY = y;
if (y < minY) minY = y;
if (curve) {
ctx.bezierCurveTo((pvalX + x) / 2, pvalY, (pvalX + x) / 2, y, x, y);
pvalX = x;
pvalY = y;
}
else {
ctx.lineTo(x, y);
}
}
ctx.lineTo((wspace*0.75), py - pstacks[0]);
ctx.lineWidth = 0;
var grad = ctx.createLinearGradient(0, minY, 0, maxY);
grad.addColorStop(0.25, colors[k % colors.length][0])
grad.addColorStop(1, colors[k % colors.length][1])
ctx.strokeStyle = colors[k % colors.length][0];
ctx.fillStyle = grad;
ctx.fill();
ctx.fillStyle = "#000"
ctx.strokeStyle = "#000"
ctx.globalAlpha = 1;
}
ctx.closePath();
}
// draw feather
base_image = new Image();
base_image.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAAEACAYAAAB7+X6nAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAACJQAAAiUBweyXgQAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7Z13vBXF2ce/z+65hUuxYUNEuFyaF0EEwRaDPRobKsYSW0w0auwKWBKPFUEs0ddujJpEDWo0aiyxYBcEgqKXJsJFEQuitFvP2XneP07b0+utnN/nA/fs7MyzszO/eZ5nnpndFYrocNC7q7s1SMNvUY40qsNQa3NVvkGZbYw+02Ndl6fEW9OciSxp6coWUVg03Fd5hqreoipboaAKqAT/Bv6pUmtUzt78kqX/TSevSIAOgrX39Nmi1PI8BhwORHe4ESJkCP9Vo/xlM2m6QC5Z2ZBMbpEAHQAbHqiqttU8h1IVTozq8BgCmMh5VX3H+Dlyy0nL1iWSXSRAO0f9fVV7gvkPsEXUibgRL7EawEUGmec4Zr9EJLBa/haKyBUN9/ffD8yrxHY+BIauxCcRmyyA6AjLtp7TO6vKYsUUCdBOUX9f5TGq+jLQPVkeCf4nCciQAGPXNzI5oYwi2hc23tv/dEv0IcBOmTGdGTBucyCoomI4dLNJS18NiShqgHaGjfdWnizwF9J1fhrEaYfAUBcVHvj2lmFdQ/mKBGhHqLuv6ghB/kqm/eLq3IT2Pwoaytun3DScG0otEqCdYMO9VWNRnQ6UQHBqlwHE/SN6tCeH6oV6/8gSKBKgXaDu7srdbfR5oDw/SRr5mUo7CDv8tOang6BIgDZH4wOVA7HkRU3h7adEgtGeoMND08FwolgyHsCT00WLKAjqH6zq7fj1TWCbvARJ5I9ClCJInl+OUA34iEW0AfTu6m71dsO7qOyaKp9Iut5Eg9M+SRcWJmaqaDlmUNEEtAHUi1VvNf49XednAAM0EWUIogkTmgYmChb5LWt0kQBtgLptK6cBR+UpRoF1QHki7z+pahd1O4cjiwRoZdTdV3WmIBfnK0dgAa41grDjl+lUMJC3d17RpiKyw8b7+h0kKk+Q1exLEnhqMhMYQjBmkKxcXIqGJQKgsLZIgFbChrsHDLEsXgEqsi0bQ4D/AdsCPaMzEWP+JcEvV0rAEviLJqAV8NXF1Vs2fCc3omyep6gvAr4+fRKedTt8ZBQW7lkkQAtDx2OXlvr+bpoY529gXk4yAmHhDcBHKCOT5YvfB0BSfyCYZIoEaGF8XzngJoVDARpX2yZHMUZV7wCOy7xITPwgRjsE4RQJ0IL4dsKgIxW5PHSshpH+OvkoWzmCTBVLTiWl00e2u4RAij5Ai+H7y4cMQPQxYtq+cY10RclGEzxv0EqUnTLJnGQfQLK8RQK0BL66uHcXx3L+CWwWe06NVDdvsD7IUNRSFZkpcHymy8MxVwv8SU6GjcXFoBZAaVnFvaqMSHa+6UfZobQHPlKr9AYR/RPKw4WqlwAqkRmjwrdFDVBgfDNx4HmqnJYmW7+mn6z3U+ZQuUBVLiHbPQJZ7BISdFWRAAXENxMGjsZwa2gFLhWa18lglPqEJ1X/ArodMCo6ubC7hASWFQlQIHx1cfWWOPJPVMrCT+WEiJCYDNs1rrFnJkhfatk8gvDHwtQsyS4hARUWFwlQAKgXy8b/hCp9CTyJE/6nMU/quOGrY7ga1rqSmsSyfm2M9X9Aac4VSrVLSDHGx0qnQf6njnxWdAILgFU/DbpchIPB1ccanIoFvS4NnolSz8pWjT9Yb3TZxhwAICJXqjFHAMPzrZOq1pkm62vjkzW+Rmk2zZSpw1ao9AF6A1tt+1P3T4sEyBOrLhg8UpXrFA2stiXYmiGQlAj+ehmjDt+JzceIvI/qe6mupyqBXUKKUSOrjY/VpknWOc3i8zdLifrpoYbtCSwWDUwuiP/JA3N9RQLkgdUTBnVvbuBJoJTgKg1uIgT/JiSCashT79bwnfV2t16+PxjDSwoGP98ZR9aroc7x0ag+mo0fNX6rBIduGLbUwIpg6F/WUJgJxU2heaGpjruBKgTX6I8QgVBSIiKE1uRV8TXx8PoVpaersiMB259zx2YOKRIgH6z8/aDjUTkldBzu3PDoT6DyQ0QI/hVAVR7H0oVqeALJw/HLDurxBOIQxV3BOaD2t4P62R7rY6AHouH4uzvyEk4LnwsSITo6s9o2zbuY0pLHgf1jzrUkZm83ZcloKD4YkjXUO9YjlvUPlB6RbdYSfhoX11O5UVNAE5wWmqi0c9Qu/SVG9o87l3Y3eO4QlRdCv4smIEt8tfLba0Vkz7AaT2D7wwM4pe3nSUv97xiPvTC0QcftF0TJLrRGMPw79LNoArLAl2cO2VfhTZHgo9spVX6QErFqPRCF+8H2+apNecktoKfGnHPldz3KVTgi1Gw3ZcnQ0EFRA2SIFSftsgXG+RuCHRn9kQ6KHuWBBA33pkb1naLnaknJEFU9JaoMLgdRcbFBw4985esnKPKY+7hIgAyhHv9DwShaJC2kuENE0IDzD9FEQII+QsBhfLrBcp6vwPMJRiQmJoC7WEA2uPdxJYwoZg7HUedxd0KRABlgxak7/1rhmLCDFmX7XUQIdZuLCODuI/mh2Wf/obycKxQGRc6F/YIASaJkE/6RNrScHi/2nrp0pTuhSIA0+PKEQb0clT8HuyicHj/vj6h8NxHc837gDyW200MME4MZo2ICRJXOMLQcqz1SEEGE/4tNK04D08DxlDyIYcvA8m5gyodrmTdutc8QnBZKJC3Qc//a8f6F0xHuVZXyqDLBpeOoqWSS6WX8NRNMLxNOIfXzbW5e8kZsalEDpMCyk4aeqY4eFvtoVqa2XyVIAtF14jfnf332kFNQDkjgF7hkB+XkEVpONIVUlTslATWKBEiCz08e1hu/My3c0GEbTEa2P5oz8scusKHBYUpI50ap/BS2P9vQcpgIrjqJxXoP8mii+yyagARQEPGZh1Rlc1yqPCq6F2UGQipfoiOBgc0hc/tsWHBPo1hXAduF1Xisyk6k8mOvqUQiirGmJ86MROpjVB7ZeuriDYnutRgISoBlx1afp5YEHCZ3IAZwv2cneQAomA+MKntZJfZqcBYglCUNDrnKh66TSHZ0XYCgvLj4QCSvT7EG9Lp14YpE91rUADFYNH5YP4PcHLWfL2oUSnAUxqYTM/oF1Lq7398WzBI101DKwg6ikfjRG6dZXBrBJTu5ExivPYJ5H03W+VDUAFFQL9ayT3aZocK+uEaqJBiFMSM9ZvQD8C0lJUPE+EYg+mZCbREsn2j0Jh79SfImkhk4dhxjDdnxzoWfJ7vnogZwYen/drnIKPtqjA2NtsHEjNrEtl/g0r51Azag3B7vF7j/ScbTy4RaIcUU0ihPpOp8KBIgjIXjhg8EbojqgBARTAoihJd+XURQ3t3pHzVP1JbV/FaV4THnwrLjzUAMEQzJiZDejKhHrSnp7rtoAggo+88P3+U1hODuXBI5U8EfaZxAMFiMwSn73CppXIIE3wHoluM2G7FyotI0gRlIqfLdPfp077sXjU9370UNACw5bNiZqBwQpfKTRt9cTmCiEarc3//Jz+aIp/FPqmyTcJSaaI2Q0AlMFFHMfArpWOr8KZN73+Q1wLIjh27r91kLVQJv3IqM/tROYJRGIJz+k1PaPNAypZvZUINometcQs0SNdLTTi8zm0KqcF+fexeek8n9b/IawNcsd6qyRba2X+Nsv6CqVw96YskPluEOVcqS2f5oJzBz25/hFLLOOFyX6f1v0hpg4cHDDxf0hWQ2GGJHv8anRf5+WlUyeMQXLPi5qLyRUE6M7U8+vYy3/YmnkPHaQy25bqf7F1yTaRtsshrgk4OHdRXlzsjolTS2n8QbO0P/0MuofkoxckfCMG0C258wtBxl++Onl6m0h6h+X+FzpmXTDpvsYlCpXyar0A8hauUNIOGCS7CcuP4Prbyp8sqgFz7771IZdiroLgQe3QosDCnuDT1BrohrYUkj6UQGd7g8rtc6hssHMsZuSjFY12/9cE3CmH8ybJImoGb/4aMt+ACwUzteyVW+K81xjI4wXc3i0iZrIRaV0bJinMmkJsZlHpKo/DRTyJrVJV1GjHpgri+bttjkTMCMsWM9YuR+NWIXYuVNDH8d8tKnn5Y22ucClfEqO6LKU5mYhCo/lRmJrreqI+dn2/mwCWqA+fsMv8Rjy61A4kBK6G8iRy04ml1pdeq3BzqbN68vabC+QNgmxapc6uml67oSrFPi8sSMfgWRv/V9rObUrBoiiE1KA8wbMmaAs8bzezU057fyFk6bNvi1eatK6q0JqGzjPpdwNTHV9DJquhejEZJoj6ATuB5jJubaJpuUBvjfoFH/QTjM09W8a1eYnwE5234RvtPyxgG2r6Lc4HyB0D2jhzoKZPtD5dXi/Mq/18Rt9swUm4wGmDdo1FEoh6Hg32hXYmiOC6RkYfvV0asGP794g1FzDUr3qBBtFrafbG1/dJ0/XbFy6/vyaZdNQgN80HvPLmVdfJ8BlaGRY3c179gVum/mQZeotfgF3zpbDN++9McdgUUIpfna/iSh5VTaw6/oXv3/WTM7m7aIxSahAcrKnYkYqXSPUqfe7o+hKdGCS9xsIOQnRHbdXLLfW2/5Ra0bUSmN8gtytP2JQsvJwseqYGBKvp0Pm4AGmFM5sg9YC4GKWBttdeGdkm7OvuG0sFftzke07UfeHPL2vAMWHTB0mGLPQ7ASzhRcMt2ysggtJ9Ueqiy0u2/crd8jtY05NksYm0AkUP6MBr7SoUqkcxBMA4O1gkaR4Ns4lfine4IIljXG5hIANfYUJKBBw3KVcG9qWCBR28lDUgP9GqhMomcDwzIUJPohUZ+onlaIzodObgJm9xt1ECpHRyW61a1hG3+dPSvTlTdR/jl0xrxPFu434ueq8otMNnbGOZMZTC9TTSFVrYv6/yt/1R9CpyVATXV1qSB3Jc0QbFxTL0Mw1CfzwEO2H8Xx++3rANTRaxP4BcmJkGhWkXBzRxrbjz424F/z7ylkO3VaAjQ0VFyiwSdwU0GVbXz19uw4JzB+182jwz6cu6hm32H7q/LzNDtyooiQTWg5afgYPqSx8axCt1OnJMAHvffcQVWugkgbp4JTJ0NVpS7ugc5Ix/gcy3NjILN1TWynZf1AZ6plZU1EBPm4udEcPuDlpU0FbSg6KQFKPM4toN3caamIIMJWzkZrjtv2R+/ZkweHvTd72YI9RhyoKvtmYvs1B9ufZAo5w24sGVv9as2PBW8oOiEBZvcbNRrRE5KdT0YEf6PsooaNsdE3VWk0+CcDGMEbZ/tTESFL2x+3KQXu8Xd1ftH/9bnrQvWcM3Jk3FdI8kGnmwYq1rTIjCq58g+dCU+9hS2dBustu4sZG7WBQ/Tu4bPmr/x0zPCD1bB39HQtzZO9ESGuKWDM4+DBcjGbUlYb9JwhL81/JpRv3phdB9iOfS0W04HnMmmLTNCpCDBrp9HjBH4WSYnMn5PBfcY0yTC7jA1qBWL7ImykyZkayGh5w2VCnea6TrjTg3P6QEwhpiYKad4LYFD5u+W3Lx381twfAOaPGLGnipwjPk5E1CNSkvd3h93oNJHAGWPHerqtqJ9P4Ju6KZDaJbQ9+pbd1YwFUJEbdp0394+f7L7bL0R5uUUf6kBfN7ZMqH79k3mfDt1tmPFYR6DmFIRBLjkLh//vfzunvr/s0Gk0QLcV9b9XGJKe0am1guOXEZZjrRVLpcRXejuAGLzhEkF17o4URkY/rtEfE1EMnovVHoq87zRb9/nX4UHk3I+HjjzEEXbERGyKBDWGIs9n0BRZoVMQ4L1Be3fXZt/VEN2tqcmQlAibOY3yttWF16prPvxx/q6jDlNjxsS9JiZEBI2M9HjbjzHIahH9AcNGNdKEQdWRElW6Gb90x5FhCH+LeAhuc+GWK1hiwm/4LBQ6BQFKm5qvQCTu9epxHZIQ8UQwfrbv2lR2ZyDVuQYVV1w+qvA6g3yLQx1Kszrix6FUjXQ1PtkKpSewLcK2hEyC22SE/mow3h8e6a6aRYiwYpd58xJ9YygvdHgCfNB7zx3AuTBVnqyJoHrv4MXvb5g7ePQh6jd+Vd5WQB3K8Ut3VXpi6Engw5DJp2Xi/hMazpp8uzggxBMBQAyPSgJ1lS86PAFKPM5NChWZ9HKGRPhOms0DAKZJrzNNMjpl7lQnQ+Y/yu5HrexlRAQU9VtEveK1UOjQBJjVb/RwVX4dlZgnEUSYOmrV3Pq5fUcfYmB0ukGXGakIB4qiVH7wRBQRQs5iWK4AvD7qszlfpLtELujQBBDVW0ASRzNzI8IPXbpUPADgCFdJ7NksAkvpMkY6PYYIIRmuWYNY+ud0YnNFhyXAzH5jDlbVgyAzNZwJEUCmVNe8tXF23z3GgvlZfM7MA0s5ESGREwhLd1049+V04nJFhyWAqIYfgc6o0dNn+qFrRZf7AFT0qhynkFlcLjpjQidQQUTvFLL63HxW6JCLQTP7jjkKGBObnmyhJ5NMqtxSXfPWxjl99xgDemBGsqLCf1ldLmnGmO3ia+wuvoczKZ4rOhwBFCyBa9PkyZwIgYw/dOtacQ+AEXNV1rJagggGMHrb8Pnz6zIplis6HAFm991jPDC8kI2uhjuqa97aOLPfmGHA4bnLyrxOGdRrnaX+gm7/SoQORYDpjLcVvSY6Ne9GX18qzXcDWKoTY1Zrk8pKjfR1SidLVG8fUfvx2iSnC4YORYC+fb86haSrfUIuWkGEu0bUfrx2dp/dK1GOT5gpAzmFrBPwrc9j355WfAHQYQgwZ+TIEoP+MbNYaMaNXm/bvj8DqCWXITGzooIRIas6IXDhHktnrc9IbJ7oMARw1ti/ASohGzuautEFfXC3pfNWz+w3Zlvg9KQZsyBC3uZB5eGRy2dPTyumQOgQBJjRd2y5IlclOpdHo/t8UnJ7UMhFCl1ynUIWsE6LSxsaL0h/hcKhQxCgXBp/B+yYKk8Ojf7E3ss/WDGzakwPQcMvVcxhClmoOjVg9MTh37XstC8W7Z4AL1UdWoZhQhrnPIwMG10t29wCII6eTYIl3YxVemGI4IjKSbuvmDMv3eUKjXZPgC38P52B0BtAkXSztDBSN7q+uPsXcz77vOrQMlG5KD9ZmWdKkqVZ0ZNG1X5UsJ2+2aBdE2A6421VuTS24/MlgmUCr1Ff4//xJIVeeUzXcsrkylKPyLjRrej0xaJdE6D3Tit/pSJVoeOCEEF5b/cvZ74fWGeRS+JzthoRalV1792XzXoJYO5Oewz5qGr36nRiC412SwAFUZHLAr9Td3w2RMDWKQAf9t3zEESHJs/YYkQwIPc0l5YMG107++N3++yzxUd9x0x2LPN47dK+i9LWv8BotwR4r3KfXyoyIpuOz4AIC0cv++glAEvNpa260BPItERh7Ojls86z6kzJrH6jryq3m79AdJJgXXM8Tzlpq1NgtFsCiOqk0O9sOz4ZEUT0ZgHzUd/dd0U4MJK/hYmgrAS90Gp2RliOMbP7jn7U43G+FrhBYQvg1d2Xzyz4nv9M0C43hLxXuc8+atg7dOz6nHJOx8G0r+wtnSdYDkatSxL1pYbzpkLmm0GA5cBTIroQtQ4wpXI1sHVMxnpVMvq4Q0ugXRLAGLks+smbvDo+9PPWUXPn+mZWjemNn6RPDwfKh8qmQnoiANtCIIYhkiSfyDVjamctT3mpFkS7MwHv77hXf+DwkBrPV/UH035s6NrlLwD4uECRkkzqUoAVv4pUsgRm1C7v0yqrfsnQ7gjgWPaFitjutFyJEH7sUuTe/Wre2vjeoL27I/wuUZlUaIkVP+A7UefktnD83GhXBJhZNaaHipwG8Z3oTsv0OJjms23nPgCryZxpsDbPN5ZQAIexCdHjR62Y+01GF25BtCsCNDhdzlKkR74d7yaPoI/vsXTWSgVLkfMzlZEOeRBBRfS3o5fPfifji7Ug2g0BpjPeRvmDO61AGuAOgA/77nkkUJmt+UiHLImgilw8evnsv2ckvBXQbmYBW/ddfQSwUyIPPudZgPDGPsvf/ziYdlFQI2QkI1laMmQwc3CA8/aonXV/WmGtiHZDAEXOgdQdkPWxkdsB3u23z3BV/Xk2MlLlSX0fobJRaFDllD1WfPRMXIE2RrsgwBs77t8f9EDIrAMyPF7ysxXvvhxMuDBbGZnmSQYXEZYgevwetR99krZQG6Bd+ADi0XMVsZLM4bM+DqbdLmDeqfrZ1oqcmKOMjMokgQKP1HftMnLM8kDnv99/r23SFWpttDkBPui9Zxej1umh4wJN/35saOjyNwD8nAOU5+hA5kqEj0X053vUzjpjG1Y3z+o3evzMnca8ZjkmZQSyLdDmBGjwdDkB2LIQHR8+Vu455Lv/1tVUV5cq8vs8tEi29ahR5AzHtg9RlR1m9h3z8Ia6bl+qynSE/R3HfjrnhmohtLkPYLDOgoI6f82C3gPwff3Wx1uY7bORkeN1GxV5B8MqLM63HPMX4gfX2/t89f6qLJqmVdCmBHi98oCBatgDCur8Pb7vine/ARDVC1rC+UtwXA4c7O7yuDwiT2TcMK2INiWAMdaZod+F0gAqgcDPm33221vR3fNZQcy1HgnSfFaz+VeGzdKqaDMfYMbYsR5Fwu/3KZAP8Pb+y2d8AiAWF+YiI8frppShIv8d8/VHa9K1SVugzQjQtLzsEKBXQTtAuQtgRtXY3qqMa0XnL52Mf2bYLK2ONiOAIqcXuAO+7tFz/fMAxmedTfBBz9bUAElIuVFLpU32/GeCNiHAK70P2VJEj4DCdQDKvaPmzvXNGTmyBOE3Be3EDI+T5Hlyn8Xvb8ikXdoCbeIEmhLrWFEtg4I5YU1qyUMAa9dsfizQK1dHLpcyqeqO8JdM26Ut0DYmQCN78gox8gzWkwcuf+O74MnzcpHRQhpg0T617xf8/b6FRKtrgP/0PWw70J8XcuRZlrkb4M0++1U7IvvkIiOXMmllKA9m3jJtg7bQAMera89fAUbezAOXvTEbwG95Mt7xU0jnL4mMZstj2s3Gj2RoCwL8CgrXAUatuwBeqjq0B8rJbaH6E8pQeX7vLz74PrMmaTu0KgGe63/UjorsWcAO+N6UWM8A2H7ndBXploOMXK6bVoZlt9z7fQuJVvUBbMc5kdDmuAL4AAbr3sOWvhz6mOJZuchoER9AmbPPsvfey7BZ2hSt7QQeV8AO8NmO8wDAy31+cYCi1TnIyIuAyequIrdm0SZtilYzAc/sdMz2iowKHeerggX918FfvRZYXrU4NxcZ7uOCOX/Kyu5bbWh3e/+SodUIUGo1Hw6Bj6QVogMM1r0A/93xoF7AEQX24LM6jkm7Y9Tcub7MWqXt0WomQFWOUOK3ZUNOanvhobUvvwPgs0vOErSk4HP4LI5daRsc234oq4ZpY7SKBpjee3wXRQ6Awow8I9a9Ajqd8baonpmLjEKo/gQyHjpo2evh7/x2BLSKBvCU+g9QIxVQkJFXj8PfASr61f9SVXrnIKMgzl+MjAb8dBjnL4TWMQEm8gr2fDtAVR4/4ssXfwqeODsXGe7jXMokkmFh7tp/5YyvM2qPdoRWMQGCHlwoFSyq90EgqAQc0pbOnythY6OnfFpmrdG+0OIa4Nkdj+6vSL8CqeDZh3/5n7kAtt/8TkXstnT+wjKEaYctfXl1lk3TLtDiGsDYVviRr3w1AHAvBPYTIvqbTMq0pAYIpq3xeUra9C0f+aDlfQDlQJXkT+UmSktyvFaa+SfAxtruhyvskEGZFtUAwYObD1v6cqu8278l0KIawIvXAsZCQTTAI0eseqE+kB6I+2dQpqU1QG1XX93dmbVG+0SLaoChlZ/upkZ6QgFGnglsrnih8og+xsjBOckoRD1cxyJ64V4rP2zIrlXaF1pUA6iRg8K/8xt5M47+8t8LABy1zgLiNpRke5yP1ggev3rw8tfa5OWOhUTLEgD5eYGcv/sh6PwpZxSiE3Mp4zpuciy7Vb/s0VJoMQIE7f8eoeM8OmBNqaf5OYB1yzc7QpFeBRi9+WqAa3+57KUlmbZFe0aLEWDnyppqYLN8O0BEHwlt+lCR32VSJpPjPGTMKu/beEs2bdGe0XImQEm49Ss6S/oG9zklDwM8U3VMb0WSRhSzPc5V9VvGnLnfW2/5s2qLdowWI4BRa0/IswOU947/8qkFADicTgGcPzeylqFy5S++fLUmi2Zo92hJJ3CvfEeesawHA+kIyukFst+5lRH5z2ErXuqwEb9kaBECPLrDqVsBAyCvkbeuvKnpaYBndxq3nyL9c5ARd5wjeb5sbi49TcAVAuwcaJFAkFNij1JEII/Ai/CPUOTPiHVmTjISHOdQpkksPfaYr59tl8/354sW0QAbSroO90nJEshdA4jRhwCe7Xv05oqMy0VGATSAqsjvfrnspTnZtkFHQYsQwKg1dL3VY10ezt+c41Y8Mw+gWUtPBrpkLSPJcTZlVOSaI5e/8LfcW6L9o4WcQKn2iWf3ZilZmEsHYEUeqhTR3xSi47OVIehfj1r+/PU53X4HQsEJ4MVrKQwBWG9vVh9Kz6ID6prt0icBpvcdv6siu7nlt4oGEHnmm622P5tNAAUnQEXlj/1BuijgxxrZQOnCbDpAkX/+euk/1gMYtaJ2/LaSBpj+3Zbbnnj23Ac6zN7+fFBwAnjEHqqEPGlhg92jAbLoAA286eOlqkPLgBMK5fxlIkPQJzfvu/bkTaXzoQUIYCzCnz9VwBF7tyarbEGGnbTwpBVPfAiw3t9jHEJP9/mW1ACC3vFx7YiTO1OYNxO0RByg2tWoAKyT7mZr1hCbnuD4gZAQRU4N/c5jDh/V4Uny+BDOG7f8uQeh3b7Mq8VQcA2gyNCg9g+PMCPW0Ear/DNXnkQjsdnnK/kbwBM7ntBLiez6KYQGSJLnR1H9xTHLn233r3JpKaQlwE0DLx2cqbDgHoABGhpbLiKss7qlVsGqz5/29WNrANQjJwN2Th585qr/Axtn5DErnn0z0/vrjEhLABV7+8kDL5t+U9UVW6fL22Pguu0VyoI75ggRQQVUrKFNVtknkLST/ho+VjklRw8+6bErzQGm/LjVlmPHHim3iwAADrJJREFU1T5Xm+g+pg28tGe6e+0sSEuAqxZPnQGyTizfZzcNvPToVHn94ukb+q2EVk4CakCBdXaP0iSd9G2vfqv+C/BY5SmjgF3c5wvo/C0T1X3H1z49KZmnf0fVhed6fH470bnOiIx8gKZm3+UgfsF6dvLAy+/39vWWJ8pnjO4UaezQvD5CBIMMabRKP4ntJIP1SMj7th3ntEKq/iB8wJ10Zfj4FU9/kKju0xlv3z7ggvvBdL9o+Z+/y6RdOgMyIoC39o61oH8I+uJnlZXWv3dz5cQ+sflE2Cn02x0LiBzDBqtHWSRPoJM8+B8FmF49vtRgFfolkm+L0V1/VTv9wuNrntqY6P7u6XPOFl9Xbf8sah2y1r+hQ7zcqVDIeBZwxZJpz6L6dKAjdaR6zKzJgy8d6c5jwm//jiCWCI7I4AYpm+fqpA9Oqn1iEUDzxtJfIvQshAYAPlWVY06sfXJseFdRAtxeddGejaWlcxU5QtVM8tY+0phpm3QGZDUN9JTK+cBaAIXt1Fgzbh5w6b6RHLp1oK8TjdwIEdZ5ulcAqggqEefPEfv0Ajh/i4xYp1m1ZsSJK558Ntm93Fl1ftltVRfeqPAuSD9g5sVf3NluX+veUsiKABNqbvlWkRtcjd7diPXSzQMn7gOAWNuFbX5MLCCEwHlrUL1dPg9oMGo9DfBw1RlbC3poIE/WGkBV5A1VOdZT6x968vLHH0v2VW4FubXqkvE+7BpFrlSwFZow1lkSclc2IWQdCfSVVNxV4qs/B+gf7ICuDubZG/pfspsqW4MggIbaUggeh5o3UGqjdOtRrs1Pn7HikbUAtt85SZGSQJHMoniKrEZ50hJzz0nLA2YkGbxjvZ5uq9YefquKF3Q4GiXHe+my2z/Nti06A7ImgLfG23z9oAmTRHnK1T09xfY8AbodRLz+kPsXGlbhTWIKjlC1xurqfr3baRl2/Ocq8jzw77LlTR8kG+khTBl04SBL7TP4ev2pirV9uHbBSxiVt3daurLT7PPPFpI+SzwU5MZBEz9CdVQiIRKjSaMNQPj428Ze3Xb0vuX1P9rv1GGq8klMeZ8iqxX53of9sVjyjlViXj1z8cNJP73m7eWt6NplY6URxqjoPhbsDTog8c0qoKtK/LrbpjTti0VOi0ECer3oZEGeAVCXanf/iozeULkonfCo9y2vH+Anu/vhJWre9Vmech92D0c8WzpYWwvaC+gF7AqcLoqZPPDyVaDuDqsX2AplB9i4mXGRLKkmCvzfgOpxm3LnQ44aAAJa4IZBkz4GHSauxGgFHrpIvEYQYw2dtHRKjXes1+P5puFLlO1jNETS8pE8GnPsTkpUj3AGn2CNu/zzaf9JfoebBnJeDRRQFW4HV7QvagoYQQIPfu6kpVNqAOxVTQcrbB8qG+ruVOUj10wQcQwnJaoHKOJDOKXY+QHktRy8ub/uiaCdBiKdoCEiSHRnhuf1oq6dtvprd9kwESQXIkg8EaIJWSeiR09YctsmN99PhrwIcMHSu5oUHgF358SOyLjO9Pn8+gTAlEETuqtwVOK1g4Rlib6WOy1+8SkiB0TkKyPsN2HJbS/lc8+dDXlvCFHLeixV6DeOCKKveL+Y9j1Ao9jHABWpyiUhUTBPsogjuIkA8obf59v9iiW3zs73fjsb8iaAd+FNnyGyIN0aQKRj7Ij6N6FPvCQvF1U2CREgWcSRDWCdP3HJLQddFfT2vX0v2jyf++1sKMiWMEWeCvxK6ngR7NB1FXVNLwLcOOTK7RH2z7CcKw0XEeLnB2EiKM8bx6m+YsnU/wvFIG8aePlh5VZZj0Lcc2dBYTaFiryiqtdAeI7tmnNHYgGK9eQlK29vAPDDCep63j82chCJKSQ6G7psMFWjcs4FJl75+S1vuKs4ecCE36M6eNKyKUUfwIWCEGBVxeq5vep61gFdFQ33UHgNAEK/wurfKL+WUDxW44I0cURwHyUMMYsswJEbrvz85ifdizo3DrlsKI411aC7lzpaTRFRyDkQFItrBl/xBsj+EaHRRABq/7R4cqWAequv2FkdCb9pI0rJa2xaID1RRYPXmSMqN/mXlP/bi9d4R3orrLrGIeI4e4nIUQL7A4LIr65aPGV6Ie61M6FgzwUo9jzB7B/4DYE2D55TBZFHw+uBjnWykiRULIEUjSJCvEkJljMgW4owzTOo4bbrmbg5Gxs2FwDLilwbHri62PkJkZQA51edX7aZZ4tTEYyjvucmL5qc+gUJyhcqyWy1qO23QupfFE4KnE+cP0KeWCLEmRQLqDShMsH0KMdQrHcdT/n5FJEQ6UyAXDn46j+JyFUCM0HewTLveUo8M70fe9e6M/5p8JWHgLwSLTzce+9du/CmnwFcNeSqfS3l7UQXTx7zJ7TilKDCKWP+c0p8HDhp2ZQO9RmX1kQ6E6A3Lbrh2qsHX/2pijwK+jOM4G9yuHrI1etRvgLWCrKFotsEi8SPVo18Q9eCE2PduGSriIG0AEIOo8YRIfHMQZH3Sks5ctLim4udnwIZxQFuWHTDv8AMBV6EcAP3UJFqhL1VdGeFnqGuCc3Pg53X1Fyi0wHOGnlWiaoclzJsS5oIX0wwyG02QtcV+Ic2lR90xac3/5Rle2xyyHoWcEW19zgxzq0CUdvCk3j+oOa56xffNA7g6uqrf4GRl935oiuRTM0nXlIOFHFTgA0icsGfFt30SFY3tQkj60jg5Brv0z9UfFelwimKhF+eFI7cScCTD41OseTJcGEjJ8bmc+eNaIQUEb6o6xHWCAgv2pa1S7Hzs0NO08CydWWWVWavMmqeV6QB9GexkbugF7/Bqih5AcDb11vejHN0XD4IzAsgydQvWTAofPa/BuO9ftHkD3O5l00dWRFg4uA/7mKLda4iJzrGbAapQ7iC/Ns711sP0FTOYYL0SBnqTRkDiDIPP4E8Jap3exffOD+beygiGhkRYMLQ64dY6tyIcrRRlUAHJvLkYwM2gXX/AJwTI6WSje7AuSREWA76GvCiZZe86q3xNmd1p0UkREoCXNz7ti4lPdZPFONMUgg80xf8AFRk/SXmOQDCawA/rK747jUAb7W3W5PRw6Li98H/E0T46hRWgsxHmC+WzjdGP7lx4Y0rCnC/RcQgKQEuH+o9XMyGu0D6BrttlQUzjPKBWLLIZzxf2Gb9j1MXT90wYdCE7pZWbC0WFyHm/KD6f/qB4CPYjWqOAqkA62XgNohMAiwx6oj+oLa9xvfjujW3B1cLi2gdxBHAO9JbUV9v36HGnKbwsiBTcKwZUxf/cXEyIVMXT90AbJg0+JoBIY3gIBH1r3JCQC3ooSLyyuQF3jtb4maKyB5RBJi483XVGxq5DPhYPLrjtPne7zMVdOlAb08sDXwkUuWrLgt5L3xSZJkKjqC2ordOHOL9eMpC7zuFuokickfYBztr5P0l3ZpWb3fbZ1d/lYugSTt7f6/BL3uKcMvNNd4J7vMTqq/dT1SfAbYQdMGPXb7Z9YFN6H187RXhQNADc8/25dr5AAZODP124PHY81NrrplhYR0KbFRk583re52X67WKKBwKsiFkwiBvL2z5CrAUXXTLAu+QZHkvG+I90BZeBtb+1GX7Xg/MPbuoBdoQhXlPoC0nKlgKiEjc6Hdj2kLv68BNCj23qv/moFR5i2h5FIQARjkhpEz8jqZ96qbLNlwvyCy/RMxGEW2DvAlw+dDr+2PJyOAiz+zbFnnTflDR+5bX7xf9jYjsnu/1i8gPeRPAqJyowcm/imvunwa31ngXqPJislfOFdE6KIAJ0BOCS7jGeCSrjZeNzXpdk6e0e/51KCJX5DULuHiX63YRI/MBFN68veaPBxSmWkW0FvLTAI51QujxLStq5a+IjoL8ngsQjgdQaG5yPEnfyVdE+0XOGuDi6htGK1IVXNF/9e5FV3bKDyt2duSsAVQY7zpIGfwpov0idwJgHRP8VeexS18oVIWKaF3kZAL+MPSGUQqVgSN5Ydr8y+sKWakiWg85EcASz3gIbwUvPnTZgZGTCVA1xwZDCBs93cteSZe/iPaLrDXAecOm7qZIfwBFX7z9w0uKe/g6MLLWAKJmPBJ8LYvydAvUqYhWRNYEUBgHIEJ9ueUpqv8OjqxMwLnVU3cFGRTcxf9i0fvv+MhOA4geF358Q0KvhiuiIyM7J1Dk2GDot74i8JBHER0cGRPgnKG3DFMYDGCwXiqq/86BjE2ACseFnvpDKar/ToKMNYARjgss/Uu9pRXFt212EmREgLNHTNtZYEjwrRyv3FNzXsIvcBbR8ZCRCVAjx4Z+W2hR/XciZKQBfMY/zsGg0FjSpayo/jsR0mqAk4bcsJMfZ1dLBQvz8l2zLlvfGhUronWQlgDGco5RVbFEELGL6r+TIS0BmnDG2SiWSlNJg7/4pa1OhpQEGDfMu43j+PZSVWzklelLryuq/06GlASo9zUeaQu2JYqR4tJvZ0RKAvjFf4xBsFR9HkuK6r8TIikB9h40obtffftZCJbom69+Oq344uVOiKQEMNJwuF+l3BJBoPjUTydFUgL4xYwTBUvFlCDPt2alimg9JHw6uKrq/LJudtNqC6u7JfLBnEX37t3aFSuidZBQA5RRf7Bf6W6JYhXVf6dGQgI4thmHgqiiYhfVfydGgsWg8TbKEQCq+tmiRQ+mfedPER0XcQQYXNVtH6AnAMK/WrtCRbQu4jWAJUeGftqqRfvfyRFPANUjgr9qaz5/5JPWrU4RrY0oAuxcdVo1woDg4bNEf82tiE6IKAIYS46KnCiq/00BMSZAQup/9YIldR+0em2KaHWECTC032+3BUYDILwITzltVakiWg9hAvhL/EeGjkWl+M6fTQQuExCe/jUZ4fU2qU0RrQ4LYGSvsyoQ9gdQeGPx4oc3tG21imgtWAD13fyHoFQAUFT/mxQsAMWE1L86ar3YhvUpopVhwXgb5JcAKG8vXfrQyjauUxGtCGvQoIo9gK0BI1jXtHWFimhdWBZyFIGP+k5c+Plfih9z3MTgUZVtVfSwxUseKb7xaxPE/wNdTWzU9o0tSgAAAABJRU5ErkJggg==';
base_image.onload = function(){
ctx.globalAlpha = 0.15
ctx.drawImage(base_image, (canvas.width/2) - 64 - (lwidth/2), (canvas.height/2) - 128);
ctx.globalAlpha = 1
}
}
/* Function for drawing line charts
* Example usage:
* quokkaLines("myCanvas", ['Line a', 'Line b', 'Line c'], [ [x1,a1,b1,c1], [x2,a2,b2,c2], [x3,a3,b3,c3] ], { stacked: true, curve: false, title: "Some title" } );
*/
function quokkaBars(id, titles, values, options) {
var canvas = document.getElementById(id);
var ctx=canvas.getContext("2d");
// clear the canvas first
ctx.clearRect(0, 0, canvas.width, canvas.height);
var lwidth = 150;
var lheight = 75;
var stack = options ? options.stack : false;
var astack = options ? options.astack : false;
var curve = options ? options.curve : false;
var title = options ? options.title : null;
var noX = options ? options.nox : false;
var verts = options ? options.verts : true;
if (noX) {
lheight = 0;
}
// Draw a border
ctx.lineWidth = 0.5;
ctx.strokeRect(25, 30, canvas.width - lwidth - 40, canvas.height - lheight - 40);
// Draw a title if set:
if (title != null) {
ctx.font="15px Arial";
ctx.fillStyle = "#000";
ctx.textAlign = "center";
ctx.fillText(title,(canvas.width-lwidth)/2, 15);
}
// Draw legend
ctx.textAlign = "left";
var posY = 50;
for (var k in titles) {
var x = parseInt(k)
if (!noX) {
x = x + 1;
}
var title = titles[k];
if (title && title.length > 0) {
ctx.fillStyle = colors[k % colors.length][0];
ctx.fillRect(canvas.width - lwidth + 20, posY-10, 10, 10);
// Add legend text
ctx.font="12px Arial";
ctx.fillStyle = "#000";
ctx.fillText(title,canvas.width - lwidth + 40, posY);
posY += 15;
}
}
// Find max and min
var max = null;
var min = 0;
var stacked = null;
for (x in values) {
var s = 0;
for (y in values[x]) {
if (y > 0 || noX) {
s += values[x][y];
if (max == null || max < values[x][y]) {
max = values[x][y];
}
if (min == null || min > values[x][y]) {
min = values[x][y];
}
}
}
if (stacked == null || stacked < s) {
stacked = s;
}
}
if (min == max) {
max++;
}
if (stack) {
min = 0;
max = stacked;
}
// Set number of lines to draw and each step
var numLines = 5;
var step = (max-min) / (numLines+1);
// Prettify the max value so steps aren't ugly numbers
if (step %1 != 0) {
step = (Math.round(step+0.5));
max = step * (numLines+1);
}
// Draw horizontal lines
for (x = numLines; x >= 0; x--) {
var y = 30 + (((canvas.height-40-lheight) / (numLines+1)) * (x+1));
ctx.moveTo(25, y);
ctx.lineTo(canvas.width - lwidth - 15, y);
ctx.lineWidth = 0.25;
ctx.stroke();
// Add values
ctx.font="10px Arial";
ctx.fillStyle = "#000";
ctx.textAlign = "right";
ctx.fillText( Math.round( ((max-min) - (step*(x+1))) * 100 ) / 100,canvas.width - lwidth + 12, y-4);
ctx.fillText( Math.round( ((max-min) - (step*(x+1))) * 100 ) / 100,20, y-4);
}
// Draw vertical lines
var sx = 1
var numLines = values.length-1;
var step = (canvas.width - lwidth - 40) / values.length;
while (step < 24) {
step *= 2
sx *= 2
}
if (verts) {
ctx.beginPath();
for (var x = 1; x < values.length; x++) {
if (x % sx == 0) {
var y = 35 + (step * (x/sx));
ctx.moveTo(y, 30);
ctx.lineTo(y, canvas.height - 10 - lheight);
ctx.lineWidth = 0.25;
ctx.stroke();
}
}
}
// Some pre-calculations of steps
var step = (canvas.width - lwidth - 48) / values.length;
var smallstep = (step / titles.length) - 2;
// Draw X values if noX isn't set:
if (noX != true) {
ctx.beginPath();
for (var i = 0; i < values.length; i++) {
smallstep = (step / (values[i].length-1)) - 2;
zz = 1
var x = 35 + ((step) * i);
var y = canvas.height - lheight + 5;
if (i % sx == 0) {
ctx.translate(x, y);
ctx.moveTo(0,0);
ctx.lineTo(0,-15);
ctx.stroke();
ctx.rotate(45*Math.PI/180);
ctx.textAlign = "left";
var val = values[i][0];
if (val.constructor.toString().match("Date()")) {
val = val.toDateString();
}
ctx.fillText(val.toString(), 0, 0);
ctx.rotate(-45*Math.PI/180);
ctx.translate(-x,-y);
}
}
}
// Draw each line
var stacks = [];
var pstacks = [];
for (k in values) {
smallstep = (step / (values[k].length)) - 2;
stacks[k] = 0;
pstacks[k] = canvas.height - 40 - lheight;
var beginX = 0;
for (i in values[k]) {
if (i > 0 || noX) {
var z = parseInt(i);
var zz = z;
if (!noX) {
z = parseInt(i) + 1;
zz = z - 2;
if (z > values[k].length) {
break;
}
}
var value = values[k][i];
var title = titles[i];
var color = colors[zz % colors.length][1];
var fcolor = colors[zz % colors.length][2];
if (values[k][2] && values[k][2].toString().match(/^#.+$/)) {
color = values[k][2]
fcolor = values[k][2]
smallstep = (step / (values[k].length-2)) - 2;
}
var x = ((step) * k) + ((smallstep+2) * zz) + 5;
var y = canvas.height - 10 - lheight;
var mdiff = (max-min);
mdiff = (mdiff == 0) ? 1 : mdiff;
var height = ((canvas.height - 40 - lheight) / (mdiff)) * value * -1;
var width = smallstep - 2;
if (width <= 1) {
width = 1
}
if (stack) {
width = step - 10;
y -= stacks[k];
stacks[k] -= height;
x = (step * k) + 4;
if (astack) {
y = canvas.height - 10 - lheight;
}
}
// Draw bar
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = color;
ctx.strokeRect(27 + x, y, width, height);
var alpha = 0.75
if (fcolor.r) {
ctx.fillStyle = 'rgba('+ [parseInt(fcolor.r*255),parseInt(fcolor.g*255),parseInt(fcolor.b*255),alpha].join(",") + ')';
} else {
ctx.fillStyle = fcolor;
}
ctx.fillRect(27 + x, y, width, height);
}
}
}
}
]==]
status_css = [[
html {
font-size: 14px;
position: relative;
background: #272B30;
}
body {
background-color: #272B30;
color: #000;
margin: 0 auto;
min-height: 100%;
font-family: Arial, Helvetica, sans-serif;
font-weight: normal;
}
.navbarLeft {
background: linear-gradient(to bottom, #F8A900 0%,#D88900 100%);
width: 200px;
height: 30px;
padding-top: 2px;
font-size: 1.35rem;
color: #FFF;
border-bottom: 2px solid #000;
float: left;
text-align: center;
}
.navbarRight {
background: linear-gradient(to bottom, #EFEFEF 0%,#EEE 100%);
width: calc(100% - 240px);
height: 28px;
color: #333;
border-bottom: 2px solid #000;
float: left;
font-size: 1.3rem;
padding-top: 4px;
text-align: left;
padding-left: 40px;
}
.wrapper {
width: 100%;
float: left;
background: #33363F;
min-height: calc(100% - 80px);
position: relative;
}
.serverinfo {
float: left;
width: 200px;
height: calc(100% - 34px);
background: #293D4C;
}
.skey {
background: rgba(30,30,30,0.3);
color: #C6E7FF;
font-weight: bold;
padding: 2px;
}
.sval {
padding: 2px;
background: rgba(30,30,30,0.3);
color: #FFF;
font-size: 0.8rem;
border-bottom: 1px solid rgba(200,200,200,0.2);
}
.charts {
padding: 0px;
width: calc(100% - 220px);
max-width: 1000px;
min-height: 100%;
margin: 0px auto;
position: relative;
float: left;
margin-left: 20px;
}
pre, code {
font-family: "Courier New", Courier, monospace;
}
strong {
font-weight: bold;
}
q, em, var {
font-style: italic;
}
/* h1 */
/* ====================== */
h1 {
padding: 0.2em;
margin: 0;
border: 1px solid #405871;
background-color: inherit;
color: #036;
text-decoration: none;
font-size: 22px;
font-weight: bold;
}
/* h2 */
/* ====================== */
h2 {
padding: 0.2em 0 0.2em 0.7em;
margin: 0 0 0.5em 0;
text-decoration: none;
font-size: 18px;
font-weight: bold;
text-align: center;
}
#modules {
margin-top:20px;
display:none;
width:400px;
}
.servers {
width: 1244px;
background: #EEE;
}
tr:nth-child(odd) {
background: #F6F6F6;
}
tr:nth-child(even) {
background: #EBEBEB;
}
td {
padding: 2px;
}
table {
border: 1px solid #333;
padding: 0px;
margin: 5px;
min-width: 360px;
background: #999;
font-size: 0.8rem;
}
canvas {
background: #FFF;
margin: 3px;
text-align: center;
padding: 2px;
border-radius: 10px;
border: 1px solid #999;
}
.canvas_wide {
position: relative;
width: 65%;
}
.canvas_narrow {
position: relative;
width: 27%;
}
a {
color: #FFA;
}
.statsbox {
border-radius: 3px;
background: #3C3E47;
min-width: 150px;
height: 60px;
float: left;
margin: 15px;
padding: 10px;
}
.btn {
background: linear-gradient(to bottom, #72ca72 0%,#55bf55 100%);
border-radius: 5px;
color: #FFF;
text-decoration: none;
padding-top: 6px;
padding-bottom: 6px;
padding-left: 3px;
padding-right: 3px;
font-weight: bold;
text-shadow: 1px 1px rgba(0,0,0,0.4);
margin: 12px;
float: left;
clear: none;
}
.infobox_wrapper {
float: left;
min-width: 200px;
margin: 10px;
}
.infobox_title {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
background: #FAB227;
color: #FFF;
border: 2px solid #FAB227;
border-bottom: none;
font-weight: bold;
text-align: center;
width: 100%;
}
.infobox {
background: #222222;
border: 2px solid #FAB227;
border-top: none;
color: #EFEFEF;
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
float: left;
width: 100%;
}
.serverinfo ul {
margin: 0px;
padding: 0px;
margin-top: 20px;
list-style: none;
}
.serverinfo ul li .btn {
width: calc(100% - 8px);
margin: 0px;
border: 0px;
border-radius: 0px;
padding: 0px;
padding-top: 8px;
padding-left: 8px;
height: 24px;
background: rgba(0,0,0,0.2);
border-bottom: 1px solid rgba(100,100,100,0.3);
}
.serverinfo ul li:nth-child(1) {
border-top: 1px solid rgba(100,100,100,0.3);
}
.serverinfo ul li .btn.active {
background: rgba(30,30,50,0.2);
border-left: 4px solid #27FAB2;
padding-left: 4px;
color: #FFE;
}
.serverinfo ul li .btn:hover {
background: rgba(50,50,50,0.15);
border-left: 4px solid #FAB227;
padding-left: 4px;
color: #FFE;
}
]]