Fix several percentage calculations | Begin adding vaccination data | Add reddit rdaily eport generator for r/Atlanta.

This commit is contained in:
Joshua Bemenderfer 2022-01-04 21:11:29 -05:00
parent 4d16a9e0b4
commit 4755f2861e
180 changed files with 723 additions and 23 deletions

View File

@ -2,11 +2,13 @@ import fs from 'fs/promises'
import fg from 'fast-glob' import fg from 'fast-glob'
import path from 'path' import path from 'path'
import StreamZip from 'node-stream-zip' import StreamZip from 'node-stream-zip'
import XLSX from 'xlsx'
import Counties from './parser/counties.js' import Counties from './parser/counties.js'
import OverallTesting from './parser/overall/testing.js' import OverallTesting from './parser/overall/testing.js'
import OverallCases from './parser/overall/cases.js' import OverallCases from './parser/overall/cases.js'
import OverallHospitalizations from './parser/overall/hospitalizations.js' import OverallHospitalizations from './parser/overall/hospitalizations.js'
import OverallDeaths from './parser/overall/deaths.js' import OverallDeaths from './parser/overall/deaths.js'
import OverallVaccinations from './parser/overall/vaccinations.js'
import RiskAge from './parser/risk/age.js' import RiskAge from './parser/risk/age.js'
import RiskHealthConditions from './parser/risk/health-conditions.js' import RiskHealthConditions from './parser/risk/health-conditions.js'
@ -14,7 +16,7 @@ import RiskHealthConditions from './parser/risk/health-conditions.js'
import Summary from './parser/summary.js' import Summary from './parser/summary.js'
async function main() { async function main() {
const sources = await fg(['./data/raw/*.zip']) const sources = await fg(['./data/raw/dph-daily-report/*.zip'])
sources.sort() sources.sort()
const zips = sources.map(source => ({ const zips = sources.map(source => ({
@ -22,12 +24,19 @@ async function main() {
zip: new StreamZip.async({ file: source }) zip: new StreamZip.async({ file: source })
})) }))
const vaccinations = await fg(['./data/raw/vaccinations/*.xlsx'])
const vaccinationSheets = vaccinations.map(source => ({
date: path.basename(source, path.extname(source)),
xlsx: XLSX.readFile(source)
}))
const counties = await Counties(zips) const counties = await Counties(zips)
await OverallTesting(zips) await OverallTesting(zips)
await OverallCases(zips, counties) await OverallCases(zips, counties)
await OverallHospitalizations(zips, counties) await OverallHospitalizations(zips, counties)
await OverallDeaths(zips, counties) await OverallDeaths(zips, counties)
await OverallVaccinations(vaccinationSheets, counties)
await RiskAge(zips) await RiskAge(zips)
await RiskHealthConditions(zips) await RiskHealthConditions(zips)

View File

@ -0,0 +1,95 @@
import mkdirp from 'mkdirp'
import path from 'path'
import fsp from 'fs/promises'
import XLSX from 'xlsx'
import { getCounty } from '../../util.js'
async function processByCounty({ date, xlsx }, countyInfo, output) {
output = {
directory: path.join(output.directory, 'by-county'),
file: county => `${county}.json`
}
const rows = XLSX.utils.sheet_to_json(xlsx.Sheets.VAX_ADMIN_BY_DAY_COUNTY)
const counties = rows.reduce((counties, row) => {
const county = getCounty(row.COUNTY_NAME)
const info = countyInfo[county]
if (!county) return counties
if (!counties[county]) counties[county] = []
counties[county].push({
report_date: row.ADMIN_DATE,
population: info.population,
vaccinations: row.VAXADMIN,
total_vaccinations: row.CUMVAXADMIN,
})
return counties
}, {})
for (const county in counties) {
const data = {
segment: { county },
headers: Object.keys(counties[county][0]),
rows: counties[county].map(row => Object.values(row))
}
await mkdirp(output.directory)
await fsp.writeFile(path.join(output.directory, output.file(county)), JSON.stringify(data))
}
}
async function processCombined({ date, xlsx }, countyInfo, output) {
output = {
directory: output.directory,
file: `combined.json`
}
const rows = XLSX.utils.sheet_to_json(xlsx.Sheets.VAX_ADMIN_BY_DAY_COUNTY)
const report_dates = new Set()
const results = rows.map(row => {
const county = getCounty(row.COUNTY_NAME)
if (!county) return null
if (['GEORGIA'].includes(county)) return null
const info = countyInfo[county]
report_dates.add(row['report_date'])
return {
county,
report_date: row.ADMIN_DATE,
population: info.population,
vaccinations: row.VAXADMIN,
total_vaccinations: row.CUMVAXADMIN,
}
}).filter(row => !!row)
const data = {
segment: { report_date: Array.from(report_dates) },
headers: Object.keys(results[0]),
rows: results.map(row => Object.values(row))
}
await mkdirp(output.directory)
await fsp.writeFile(path.join(output.directory, output.file), JSON.stringify(data))
}
async function processSingleWorkbook (xlsx, countyInfo) {
const output = {
directory: `./public/data/overall/vaccinations/`,
}
try {
await fsp.rm(output.directory, { recursive: true })
} catch (e) {}
await processByCounty(xlsx, countyInfo, output)
await processCombined(xlsx, countyInfo, output)
}
function process (vaccinationSources, countyInfo) {
return processSingleWorkbook(vaccinationSources.at(-1), countyInfo)
}
export default process

129
data/parser/reddit/index.js Normal file
View File

@ -0,0 +1,129 @@
import mkdirp from 'mkdirp'
import path from 'path'
import fsp from 'fs/promises'
function normalize(data) {
return data.rows.map(row => {
const obj = {}
row.forEach((col, i) => {
obj[data.headers[i]] = col
})
return obj
})
}
function percentChange (current, prev) {
const change = current - prev
let percent = (change / Math.abs(prev)) * 100
if (isNaN(percent)) return 0
const sign = percent > 0 ? '+' : '-'
if (Math.abs(percent) === Infinity) percent = 100
return `${sign}${Math.abs(percent.toFixed(2)).toLocaleString()}`
}
function replaceVariables (template, variables) {
Object.keys(variables).forEach(key => {
let value = variables[key]
if (typeof value === 'number') value = value.toLocaleString()
template = template.split(`{${key}}`).join(value)
})
return template
}
async function readJSON(file) {
return JSON.parse(await fsp.readFile(file, 'utf-8'))
}
async function process () {
const template = await fsp.readFile('./data/parser/reddit/template.md', 'utf-8')
const data = {
tests: normalize(await readJSON('./public/data/overall/testing/by-county/-- All --.json')).reverse(),
cases: normalize(await readJSON('./public/data/overall/cases/by-county/-- All --.json')).reverse(),
hospitalizations: normalize(await readJSON('./public/data/overall/hospitalizations/by-county/-- All --.json')).reverse(),
deaths: normalize(await readJSON('./public/data/overall/deaths/by-county/-- All --.json')).reverse(),
vaccinations: normalize(await readJSON('./public/data/overall/vaccinations/by-county/-- All --.json')).reverse(),
}
function formatRow(data, index) {
const prevData = {
tests: data.tests[index + 1],
cases: data.cases[index + 1],
hospitalizations: data.hospitalizations[index + 1],
deaths: data.deaths[index + 1],
vaccinations: data.vaccinations[index + 1],
}
const currentData = {
tests: data.tests[index],
cases: data.cases[index],
hospitalizations: data.hospitalizations[index],
deaths: data.deaths[index],
vaccinations: data.vaccinations[index],
}
currentData.hospitalizations.total_hospitalizations = data.hospitalizations.reduce((total, r) => {
return total + r.hospitalizations
}, 0)
const date = new Date(`${currentData.tests.report_date} 23:59:59`)
const date_short = `${`${(date.getMonth() + 1)}`.padStart(2, '0')}/${`${date.getDate()}`.padStart(2, '0')}`
const computedData = {
date,
date_short,
date_long: date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }),
current_percent_positive: Math.round(currentData.tests.seven_day_percent_positive),
current_tests: currentData.tests.combined_performed_running_total.toLocaleString(),
current_cases: currentData.cases.total_cases.toLocaleString(),
current_hospitalizations: currentData.hospitalizations.total_hospitalizations.toLocaleString(),
current_deaths: currentData.deaths.total_deaths.toLocaleString(),
current_vaccinations: currentData.vaccinations.total_vaccinations.toLocaleString(),
current_tests_increase: (currentData.tests.combined_performed - prevData.tests.combined_performed).toLocaleString(),
current_cases_increase: currentData.cases.cases.toLocaleString(),
current_hospitalizations_increase: currentData.hospitalizations.hospitalizations.toLocaleString(),
current_deaths_increase: currentData.deaths.deaths.toLocaleString(),
current_vaccinations_increase: currentData.vaccinations.vaccinations.toLocaleString(),
current_tests_change_percent: percentChange(currentData.tests.combined_performed, prevData.tests.combined_performed),
current_cases_change_percent: percentChange(currentData.cases.cases, prevData.cases.cases),
current_hospitalizations_change_percent: percentChange(currentData.hospitalizations.hospitalizations, prevData.hospitalizations.hospitalizations),
current_deaths_change_percent: percentChange(currentData.deaths.deaths, prevData.deaths.deaths),
current_vaccinations_change_percent: percentChange(currentData.vaccinations.vaccinations, prevData.vaccinations.vaccinations),
}
return computedData
}
const results = []
for (let i = 0; i <= 30; i++) {
results.push(formatRow(data, i))
}
const variables = {
...results.at(0),
table_rows: results.map(row => {
return `| ${[
row.date_short,
`${row.current_percent_positive}%`,
`${row.current_cases_increase} [${row.current_cases_change_percent}%]`,
`${row.current_hospitalizations_increase} [${row.current_hospitalizations_change_percent}%]`,
`${row.current_deaths_increase} [${row.current_deaths_change_percent}%]`,
`${row.current_vaccinations_increase} [${row.current_vaccinations_change_percent}%]`,
].join(' | ')} |`
}).join('\n')
}
console.log(replaceVariables(template, variables))
}
process()

View File

@ -0,0 +1,54 @@
**{date_long} Case + Vaccine Update**
This post is an attempt to accurately represent a few helpful statistics provided by the Georgia Department of Public Health (DPH) at the time of posting.
---------------------
Total Tests (PCR + Antigen): {current_tests}
Tests Reported Today: {current_tests_increase} ({current_tests_change_percent}% day-over-day)
7-Day Percent Positive: {current_percent_positive}%
-------------------
Total Confirmed Cases (PCR + Antigen): {current_cases}
Cases Reported Today: {current_cases_increase} ({current_cases_change_percent}% day-over-day)
---------------------
Total Hospitalizations: {current_hospitalizations}
Hospitalized Today: {current_hospitalizations_increase} ({current_hospitalizations_change_percent}% day-over-day)
---------------------
Total Deaths: {current_deaths}
Deaths Reported Today: {current_deaths_increase} ({current_deaths_change_percent}% day-over-day)
---------------------
Total Vaccine Doses Administered: {current_vaccinations}
Vaccine Doses Reported Today: {current_vaccinations_increase} ({current_vaccinations_change_percent}% day-over-day)
---------------------
**Each column below contains the following space-separated values:**
Contents of New Cases, New Hospitalizations, New Deaths, and New Vaccine Doses columns:
- The day-over-day increase [The day-over-day change as a percent of the previous day]
| Date | Test % Positive | New Cases | New Hospitalizations | New Deaths | New Vaccine Doses |
| ---- | --------------- | --------- | -------------------- | ---------- | ----------------- |
{table_rows}
Final data for December 2021, with links to posts starting in March 2020 courtesy of /u/diemunkiesdie can be found here: https://www.reddit.com/r/Atlanta/comments/rpkf94/comment/hqq24ct/
---------------------
**Sourced from today's Georgia DPH COVID-19 Report and Vaccination Data:**
- https://dph.georgia.gov/covid-19-daily-status-report
- https://experience.arcgis.com/experience/3d8eea39f5c1443db1743a4cb8948a9c

Binary file not shown.

View File

@ -1,5 +1,6 @@
export function getCounty (county) { export function getCounty (county) {
if (county === 'Georgia') return '-- All --' if (!county) return county
if (county.toLowerCase() === 'georgia') return '-- All --'
if (county === 'Non-GA Resident/Unknown State') return '-- Unknown --' if (county === 'Non-GA Resident/Unknown State') return '-- Unknown --'
return county return county.split('County').join('').split('county').join('').trim()
} }

263
package-lock.json generated
View File

@ -11,7 +11,8 @@
"dependencies": { "dependencies": {
"jscharting": "^3.2.2", "jscharting": "^3.2.2",
"mkdirp": "^1.0.4", "mkdirp": "^1.0.4",
"papaparse": "^5.3.1" "papaparse": "^5.3.1",
"xlsx": "^0.17.4"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/healthicons": "^1.0.3", "@iconify-json/healthicons": "^1.0.3",
@ -843,6 +844,21 @@
"node": ">=0.4.0" "node": ">=0.4.0"
} }
}, },
"node_modules/adler-32": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
"integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
"dependencies": {
"exit-on-epipe": "~1.0.1",
"printj": "~1.1.0"
},
"bin": {
"adler32": "bin/adler32.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/ansi-styles": { "node_modules/ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -1140,6 +1156,52 @@
"url": "https://github.com/sponsors/wooorm" "url": "https://github.com/sponsors/wooorm"
} }
}, },
"node_modules/cfb": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.1.tgz",
"integrity": "sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ==",
"dependencies": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0",
"printj": "~1.3.0"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cfb/node_modules/adler-32": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.0.tgz",
"integrity": "sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g==",
"dependencies": {
"printj": "~1.2.2"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cfb/node_modules/adler-32/node_modules/printj": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.2.3.tgz",
"integrity": "sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA==",
"bin": {
"printj": "bin/printj.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cfb/node_modules/printj": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.3.0.tgz",
"integrity": "sha512-017o8YIaz8gLhaNxRB9eBv2mWXI2CtzhPJALnQTP+OPpuUfP0RMWqr/mHCzqVeu1AQxfzSfAtAq66vKB8y7Lzg==",
"bin": {
"printj": "bin/printj.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/chalk": { "node_modules/chalk": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -1235,6 +1297,14 @@
"mimic-response": "^1.0.0" "mimic-response": "^1.0.0"
} }
}, },
"node_modules/codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/color-convert": { "node_modules/color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -1295,6 +1365,21 @@
"node": ">=10" "node": ">=10"
} }
}, },
"node_modules/crc-32": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
"integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
"dependencies": {
"exit-on-epipe": "~1.0.1",
"printj": "~1.1.0"
},
"bin": {
"crc32": "bin/crc32.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -2059,6 +2144,14 @@
"url": "https://github.com/sindresorhus/execa?sponsor=1" "url": "https://github.com/sindresorhus/execa?sponsor=1"
} }
}, },
"node_modules/exit-on-epipe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/extend": { "node_modules/extend": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@ -2165,6 +2258,14 @@
"node": ">=0.4.x" "node": ">=0.4.x"
} }
}, },
"node_modules/frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/fraction.js": { "node_modules/fraction.js": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz",
@ -4684,6 +4785,17 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true "dev": true
}, },
"node_modules/printj": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ==",
"bin": {
"printj": "bin/printj.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/promise": { "node_modules/promise": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
@ -5171,6 +5283,17 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true "dev": true
}, },
"node_modules/ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"dependencies": {
"frac": "~1.1.2"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/string.prototype.trimend": { "node_modules/string.prototype.trimend": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
@ -5979,6 +6102,22 @@
"node": ">= 10.0.0" "node": ">= 10.0.0"
} }
}, },
"node_modules/wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/wrappy": { "node_modules/wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@ -6021,6 +6160,26 @@
"deasync": "^0.1.0" "deasync": "^0.1.0"
} }
}, },
"node_modules/xlsx": {
"version": "0.17.4",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.17.4.tgz",
"integrity": "sha512-9aKt8g9ZLP0CUdBX8L5xnoMDFwSiLI997eQnDThCaqQMYB9AEBIRzblSSNN/ICMGLYIHUO3VKaItcedZJ3ijIg==",
"dependencies": {
"adler-32": "~1.2.0",
"cfb": "^1.1.4",
"codepage": "~1.15.0",
"crc-32": "~1.2.0",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
},
"bin": {
"xlsx": "bin/xlsx.njs"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/xtend": { "node_modules/xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@ -6790,6 +6949,15 @@
"integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==", "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
"dev": true "dev": true
}, },
"adler-32": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.2.0.tgz",
"integrity": "sha1-aj5r8KY5ALoVZSgIyxXGgT0aXyU=",
"requires": {
"exit-on-epipe": "~1.0.1",
"printj": "~1.1.0"
}
},
"ansi-styles": { "ansi-styles": {
"version": "4.3.0", "version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
@ -7006,6 +7174,38 @@
"integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==",
"dev": true "dev": true
}, },
"cfb": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.1.tgz",
"integrity": "sha512-wT2ScPAFGSVy7CY+aauMezZBnNrfnaLSrxHUHdea+Td/86vrk6ZquggV+ssBR88zNs0OnBkL2+lf9q0K+zVGzQ==",
"requires": {
"adler-32": "~1.3.0",
"crc-32": "~1.2.0",
"printj": "~1.3.0"
},
"dependencies": {
"adler-32": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.0.tgz",
"integrity": "sha512-f5nltvjl+PRUh6YNfUstRaXwJxtfnKEWhAWWlmKvh+Y3J2+98a0KKVYDEhz6NdKGqswLhjNGznxfSsZGOvOd9g==",
"requires": {
"printj": "~1.2.2"
},
"dependencies": {
"printj": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.2.3.tgz",
"integrity": "sha512-sanczS6xOJOg7IKDvi4sGOUOe7c1tsEzjwlLFH/zgwx/uyImVM9/rgBkc8AfiQa/Vg54nRd8mkm9yI7WV/O+WA=="
}
}
},
"printj": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.3.0.tgz",
"integrity": "sha512-017o8YIaz8gLhaNxRB9eBv2mWXI2CtzhPJALnQTP+OPpuUfP0RMWqr/mHCzqVeu1AQxfzSfAtAq66vKB8y7Lzg=="
}
}
},
"chalk": { "chalk": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
@ -7074,6 +7274,11 @@
"mimic-response": "^1.0.0" "mimic-response": "^1.0.0"
} }
}, },
"codepage": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz",
"integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA=="
},
"color-convert": { "color-convert": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
@ -7124,6 +7329,15 @@
"yaml": "^1.10.0" "yaml": "^1.10.0"
} }
}, },
"crc-32": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
"integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
"requires": {
"exit-on-epipe": "~1.0.1",
"printj": "~1.1.0"
}
},
"cross-spawn": { "cross-spawn": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
@ -7653,6 +7867,11 @@
"strip-final-newline": "^2.0.0" "strip-final-newline": "^2.0.0"
} }
}, },
"exit-on-epipe": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
"integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
},
"extend": { "extend": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
@ -7737,6 +7956,11 @@
"integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=", "integrity": "sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs=",
"dev": true "dev": true
}, },
"frac": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz",
"integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA=="
},
"fraction.js": { "fraction.js": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz", "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.1.2.tgz",
@ -9470,6 +9694,11 @@
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
"dev": true "dev": true
}, },
"printj": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
"integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
},
"promise": { "promise": {
"version": "7.3.1", "version": "7.3.1",
"resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz",
@ -9845,6 +10074,14 @@
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
"dev": true "dev": true
}, },
"ssf": {
"version": "0.11.2",
"resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz",
"integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==",
"requires": {
"frac": "~1.1.2"
}
},
"string.prototype.trimend": { "string.prototype.trimend": {
"version": "1.0.4", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
@ -10440,6 +10677,16 @@
"babel-walk": "3.0.0-canary-5" "babel-walk": "3.0.0-canary-5"
} }
}, },
"wmf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz",
"integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw=="
},
"word": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz",
"integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA=="
},
"wrappy": { "wrappy": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
@ -10476,6 +10723,20 @@
"vfile": "^5.0.0" "vfile": "^5.0.0"
} }
}, },
"xlsx": {
"version": "0.17.4",
"resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.17.4.tgz",
"integrity": "sha512-9aKt8g9ZLP0CUdBX8L5xnoMDFwSiLI997eQnDThCaqQMYB9AEBIRzblSSNN/ICMGLYIHUO3VKaItcedZJ3ijIg==",
"requires": {
"adler-32": "~1.2.0",
"cfb": "^1.1.4",
"codepage": "~1.15.0",
"crc-32": "~1.2.0",
"ssf": "~0.11.2",
"wmf": "~1.0.1",
"word": "~0.3.0"
}
},
"xtend": { "xtend": {
"version": "4.0.2", "version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",

View File

@ -31,6 +31,7 @@
"dependencies": { "dependencies": {
"jscharting": "^3.2.2", "jscharting": "^3.2.2",
"mkdirp": "^1.0.4", "mkdirp": "^1.0.4",
"papaparse": "^5.3.1" "papaparse": "^5.3.1",
"xlsx": "^0.17.4"
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More