You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
1.9 KiB
JavaScript

// SARS-CoV-2-Viz
// Animated COVID case count visualization
// Copyright 2022 Edward L. Platt <ed@elplatt.com>
// Convert csv to tsv
// Assumes quoted strings do not contain escaped quotes
async function csvToTSV(csv, onProgress) {
onProgress("parsing CSV: 0 of ? parts");
let quoteParts = csv.split('"');
let tsv = "";
const rowCount = quoteParts.length;
let percent = 0;
let partStack = quoteParts.reverse();
return new Promise((resolve, reject) => {
let index = 0;
let processPart = () => {
while (true) {
if (partStack.length == 0) {
resolve(tsv);
break;
}
part = partStack.pop();
if (index % 2 == 0) {
// Not quoted
tsv += part.replace(/,/g, "\t");
} else {
// Quoted
tsv += part;
}
index += 1;
let newPercent = Math.floor(100 * index / rowCount);
if (newPercent > percent) {
percent = newPercent;
onProgress(`parsing CSV: ${index} of ${rowCount} parts`);
setTimeout(processPart, 0);
break;
}
}
}
setTimeout(processPart, 0);
});
}
function tsvRowToJSON(keys, tsvRow) {
let row = {};
let rowParts = tsvRow.split("\t");
for (const [index, key] of keys.entries()) {
row[key] = rowParts[index];
}
return row;
}
function tsvToJSON(tsv, onProgress) {
const lines = tsv.split(/\n/);
let columnNames = [];
let data = [];
const count = lines.length;
for (const [row, line] of lines.entries()) {
if (row == 0) {
columnNames = line.split("\t").map((x) => x.trim());
} else {
let dataRow = {};
for (const [col, cell] of line.split("\t").entries()) {
dataRow[columnNames[col]] = cell.trim();
}
// Limit to US Counties
if (dataRow["iso3"] == "USA"
&& dataRow["Admin2"] != ""
&& dataRow["Admin2"] != "Unassigned"
&& dataRow["FIPS"] != "") {
data.push(dataRow);
}
}
let progress = count / row;
onProgress(progress);
}
return data;
}