Compare COVID19 Cases by State
var dsource = "Https://covidtracking.com";
function rawToObjects(data) {
console.log(data);
latestDate = new moment(String(data[0]["date"]), "YYYYMMDD");
var r = {};
data.forEach(d => {
if (!r.hasOwnProperty(d["state"])) {
r[d["state"]] = {
positive: {},
negative: {},
death: {},
deathrt: {},
proc: {},
droc: {},
drroc: {},
}
}
var e = r[d["state"]];
var ddt = new moment(String(d["date"]), "YYYYMMDD");
var index = ddt.format("YYYY-MM-DD");
e["positive"][index] = d["positive"];
e["negative"][index] = d["negative"];
e["death"][index] = d["death"];
e["deathrt"][index] = Math.round(d["death"] / d["positive"] * 10000) / 100;
});
for (var i in r) {
var e = r[i];
for (var index in e["positive"]) {
var prev = new moment(String(index), "YYYY-MM-DD").subtract(1, "day").format("YYYY-MM-DD");
if (e["positive"].hasOwnProperty(prev)) {
e["proc"][index] = Math.round((e["positive"][index] - e["positive"][prev]) / e["positive"][prev] * 100);
e["droc"][index] = Math.round((e["death"][index] - e["death"][prev]) / e["death"][prev] * 100);
e["drroc"][index] = Math.round((e["deathrt"][index] - e["deathrt"][prev]) / e["deathrt"][prev] * 100);
}
}
}
console.log(r);
processData(r);
}
function getData() {
fetch("https://covidtracking.com/api/states/daily")
.then(response => response.json())
.then(rawToObjects)
}
var latestDate = 0;
var processed;
var myChart;
var toShow = [];
var lineColorCounter = 0;
var baselineColorCounter = 0;
var outbreak = true;
var fullCSV = "";
var lineColors = [
'rgba(68, 114, 196, 1)',
'rgba(255, 192, 0, 1)',
'rgba(112, 173, 71, 1)',
'rgba(0, 63, 105, 1)',
'rgba(132, 60, 12, 1)',
'rgba(234, 20, 31, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)'
];
var baslineColors = [
'rgba(0, 168, 255, 0.25)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)',
'rgba(112, 173, 71, 1)'
];
function coreGenLables(t) {
var e = t.data.datasets,
i = t.options.legend || {},
n = i.labels && i.labels.usePointStyle;
return t._getSortedDatasetMetas().map((function(t) {
var i = t.controller.getStyle(n ? 0 : void 0);
return {
text: e[t.index].label,
fillStyle: i.backgroundColor,
hidden: !t.visible,
lineCap: i.borderCapStyle,
lineDash: i.borderDash,
lineDashOffset: i.borderDashOffset,
lineJoin: i.borderJoinStyle,
lineWidth: 8,
strokeStyle: i.borderColor,
pointStyle: i.pointStyle,
rotation: i.rotation,
datasetIndex: t.index
}
}), this)
}
function drawString(ctx, text, posX, posY, textColor, rotation, font, fontSize) {
var lines = text.split("\n");
if (!rotation) rotation = 0;
if (!font) font = "'serif'";
if (!fontSize) fontSize = 16;
if (!textColor) textColor = '#000000';
ctx.save();
ctx.font = fontSize + "px " + font;
ctx.fillStyle = textColor;
ctx.translate(posX, posY);
ctx.rotate(rotation * Math.PI / 180);
for (i = 0; i < lines.length; i++) {
ctx.fillText(lines[i], 0, i * fontSize);
}
ctx.restore();
}
Chart.plugins.register({
beforeDraw: function(chart, easing) {
if (chart.config.options.chartArea && chart.config.options.chartArea.backgroundColor) {
var ctx = chart.ctx;
var chartArea = chart.chartArea;
ctx.save();
ctx.fillStyle = chart.config.options.chartArea.backgroundColor;
ctx.fillRect(chartArea.left, chartArea.top, chartArea.right - chartArea.left, chartArea.bottom - chartArea.top);
ctx.restore();
}
}
});
Chart.plugins.register({
afterDraw: function(chart, easing) {
var ctx = chart.ctx;
drawString(ctx, "InfoMullet.com\nSource: " + dsource + "\nCurrent as of: " + latestDate.format("YYYY-MM-DD"), 0, 16);
}
});
Chart.defaults.fontSize = 24;
Chart.defaults.fontFamily = "Calibri";
function downloadCanvas(canvas, filename) {
console.log(canvas);
var lnk = document.createElement('a');
lnk.download = filename;
lnk.href = canvas.toDataURL("image/png;base64");
if (document.createEvent) {
e = document.createEvent("MouseEvents");
e.initMouseEvent("click", true, true, window,
0, 0, 0, 0, 0, false, false, false,
false, 0, null);
lnk.dispatchEvent(e);
} else if (lnk.fireEvent) {
lnk.fireEvent("onclick");
}
}
function genFullCSV(data, labels, dp) {
fullCSV = "Location\tDatapoint\t" + labels.join("\t") + "\n";
for (const key in data) {
var vals = [];
for (var i = 0; i {
var opt = $('').val(newKey).text(newKey);
if (toShow.includes(newKey)) {
opt.prop('selected', true);
}
$('#countrylist').append(opt);
});
$('#countrylist').trigger("chosen:updated");
}
function generateBase(title, index, label) {
var color = processed[title]["baseColor"] ? baslineColors[baselineColorCounter++] : lineColors[lineColorCounter++];
return {
label: title + label,
fill: false,
borderWidth: processed[title]["width"],
borderColor: color,
backgroundColor: color,
pointHitRadius: 10,
pointRadius: 0,
yAxisID: "yaxis",
xAxisID: "xaxis",
pointBackgroundColor: 'rgba(0,0,0,0)',
pointBorderColor: 'rgba(0,0,0,0)',
data: processed[title][index],
};
}
function toPoints(labels, data) {
var ret = [];
labels.forEach((label, i) => {
ret.push({
x: label,
y: data[label]
});
});
return ret;
}
function createDatasetObject() {
var set = [];
toShow.forEach(x => {
set.push(generateBase(x, 'points', ""))
})
return set;
}
function refreshChart() {
toShow = $("#countrylist").chosen().val();
if (outbreak)
toShow.push("Outbreak Threshold Risk");
lineColorCounter = 0;
baselineColorCounter = 0;
toShow.sort();
myChart.data.datasets = createDatasetObject();
myChart.update({
duration: 800,
easing: 'easeInQuad'
});
}
$(document).ready(function() {
$('head').append('');
$('head').append('');
$('#chartholder').append('');
$('#controlholder').append('');
$('#controlholder').append('');
$('#controlholder').css("display", "inline-block");
$('#chartholder').css("display", "inline-block");
$('#controlholder').append('');
$("#get_csv").on('click', function(e) {
downloadCSV()
});
$("#get_PNG").on('click', function(e) {
downloadCanvas($("#chartCanvas").get(0), "chart.png")
});
$("#countrylist").chosen({
max_selected_options: 6
}).change(refreshChart);
getData();
});
outbreak = false;
function processData(data) {
toShow = ['ME', 'NY', 'MA', 'CA', 'WA', "Outbreak Threshold Risk"];
processed = {labels:[]};
for(var dt = latestDate.clone(); latestDate.diff(dt, "day") {
processed['Outbreak Threshold Risk']["points"].push(800)
});
console.log(processed);
var ctx = document.getElementById('chartCanvas').getContext('2d');
var yticks = [1, 10, 100, 1000, 10000, 100000, 1000000];
myChart = new Chart(ctx, {
type: 'line',
responsive: false,
data: {
labels: processed["labels"],
datasets: createDatasetObject()
},
options: {
aspectRatio:1000/800,
title: {
display: true,
text: ["Select State Confirmed Cases COVID19", "(Logarithmic Scale)"]
},
legend: {
position: 'bottom',
labels: {
boxWidth: 12,
fontSize: 14,
generateLabels: coreGenLables
},
},
chartArea: {
backgroundColor: 'rgba(235, 235, 235, 1)'
},
scales: {
xaxis: {
type: 'category',
gridLines: {
display: false
},
scaleLabel: {
display: true,
labelString: "LAST 90 DAYS",
fontSize: 32
},
ticks: {
autoSkip: false,
},
afterFit: function(axis) {
axis.ticks.forEach((e,i,a)=>{if(i > 0 && i % 10 != 9) {e.label="";}});
}
},
yaxis: {
type: "logarithmic",
scaleLabel: {
display: true,
labelString: "TOTAL CONFIRMED CASES",
fontSize: 32
},
ticks: {
autoSkip: true,
min: yticks[0],
max: yticks[yticks.length-1],
},
beforeBuildTicks: function(s) {
s.min = yticks[0];
s.max = yticks[yticks.length - 1];
},
afterBuildTicks: function(s) {
s.ticks = s.ticks.filter(t => yticks.includes(t.value));
}
}
}
}
});
$(".main-container").width("100%");
$("#page").width("100%");
$("#page").css("maxWidth","100%");
}