├── .gitignore ├── LICENSE ├── README.md ├── bin ├── 1_download.js ├── 2_deduplicate.js ├── 3_parse.js ├── 4_check.js ├── 5_index_data.js ├── 6_upload.sh ├── 7_recompress.js ├── lib │ ├── config.js │ └── helper.js ├── loop.sh ├── recompress.sh └── run.sh ├── data └── landkreise.json ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .DS_Store 3 | /bin/z_* 4 | /data/0_archived 5 | /data/1_ignored 6 | /data/2_parsed 7 | /data/z_* 8 | /node_modules/ 9 | /tmp/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 4 | Code: Michael Kreil (BR) 5 | Data: RKI (https://rki.de) DL-DE-BY-2.0 (https://www.govdata.de/dl-de/by-2-0) 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RKI-Corona-Daten-Archiv 2 | 3 | ## Worum geht es? 4 | 5 | Das RKI veröffentlicht täglich die [gemeldeten Coronafälle in einer Tabelle](https://npgeo-corona-npgeo-de.hub.arcgis.com/datasets/dd4580c810204019a7b8eb3e0b329dd6_0), aufgeschlüsselt u.a. nach Meldedatum, Alter, Geschlecht, Landkreis etc. 6 | 7 | Diese Daten liegen unter einer offenen, mit CC-BY kompatiblen Lizenz vor: Robert Koch-Institut, [dl-de-by-2.0](https://www.govdata.de/dl-de/by-2-0) 8 | 9 | Leider werden die alten Versionen dieser Daten täglich überschrieben. Das hat zur Folge, dass man bspw. nicht den Verzug zwischen Erkrankungsbeginn und Veröffentlichung analysieren kann, was aber zentral z.B. für eigene Nowcasting-Berechnungen ist. 10 | 11 | Daher sammeln wir alte Datei-Versionen und stellen sie online ebenfalls unter RKI dl-de-by-2.0 zur Verfügung. Per Scraper versuchen wir das Archiv täglich aktuell zu halten. Als Feature bereinigen wir sogar die Daten, um z.B. die Probleme mit den unterschiedlichen Datumsformaten zu korrigieren. 12 | 13 | ## Daten 14 | 15 | ### Wo sind die Daten zu finden? 16 | 17 | - Die Rohdaten werden täglich im Ordner `0_archived` ergänzt und im Anschluss [hier als HTML-Datei](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/0_archived/index.html) oder [wahlweise als TXT-Datei](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/0_archived/index.txt) chronologisch sortiert aufgelistet. 18 | - Fehlerhafte Rohdaten werden nach `1_ignored` verschoben, z.B. wenn durch technische Probleme nur Teile der CSV-Datei zum Download standen: [HTML](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/1_ignored/index.html)/[TXT](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/1_ignored/index.txt) 19 | - **Gesäuberte Daten werden täglich unter `2_parsed` hochgeladen und sind hier aufgelistet als [HTML](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/index.html) oder [TXT](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/index.txt)** 20 | 21 | ### Welches Format haben sie? 22 | 23 | Da die Datenmenge sehr stark angewachsen ist und einzelne Dumps über 500 MB groß werden können, so dass die 1-GB-Stringlängenbegrenzung von JavaScript überschritten wird, musste auf ein neues Datenformat umgestiegen werden. Die Dateien liegen jetzt vor: 24 | - als [NDJSON](http://ndjson.org) (jede Zeile ist ein Eintrag, als JSON-Objekt formatiert und endet auf '\n') und 25 | - mit [XZ-Utils](https://tukaani.org/xz/format.html) komprimiert (XZ/LZMA ist sehr effektiv, open-source, kostenlos, plattformübergreifend erhältlich und wird von vielen Kompressionsprogrammen unterstützt) 26 | 27 | ### Datenfelder 28 | 29 | Die Datenfelder sind vom RKI [auf der ArcGIS-Plattform](https://npgeo-corona-npgeo-de.hub.arcgis.com/datasets/dd4580c810204019a7b8eb3e0b329dd6_0) erklärt. 30 | 31 | Es hat sich aber gezeigt, dass insbesondere die Datumsfelder in einem schlechten Zustand sind. Neben unterschiedlichen Datumsformaten, gibt es sogar Infektionsfälle aus dem Jahr 1956. Der Parser korrigiert die gröbsten Fehler und ergänzt die Datensätze um die Felder `MeldedatumISO`, `DatenstandISO` und `RefdatumISO`, die das jeweilige Datum immer in der ISO-Form `"YYYY-MM-DD"` formatieren. 32 | 33 | [Hier noch eine kurze Erklärung](https://github.com/ard-data/2020-rki-archive/issues/2#issuecomment-770791045), warum Fallzahlen negativ sein können. 34 | 35 | Ansonsten haben wir uns bemüht darauf zu achten, keine Fehler zu machen. Falls uns trotzdem einer unterlaufen ist, freuen wir uns über Hinweise. 36 | 37 | Diese Daten sind natürlich keine offizielle Veröffentlichung des RKI oder der ARD, sondern eine freundliche Unterstützung für Forschung und Recherche. Offizielle Daten gibt es nur beim RKI. 38 | 39 | ### Verzeichnis `/bin/` 40 | 41 | Der Code läuft aktuell nur unter UNIX-Betriebssystemen, also z.B. Linux/Mac OS. Er dient dem Scrapen und Säubern der Daten. 42 | 43 | - `bin/1_download.js` überprüft all 10 Minuten, ob das RKI die Daten aktualisiert hat, und lädt sie ggf. runter. 44 | - `bin/2_deduplicate.sh` löscht doppelte Dateien, also wenn es keine Änderungen an den Daten gab. 45 | - `bin/3_parse.js` parst die API-/CSV-Rohdaten und macht daraus sauberes und einheitliches JSON. 46 | - `bin/4_check.js` führt Plausibilitätschecks durch. Z.B. darf die Anzahl aller bisherigen Infektionen nicht sinken, aber auch nicht um mehr als 30'000 ggü. dem Vortag steigen.. 47 | - `bin/5_index_data.js` generiert HTML- und TXT-Listen als Hilfe for den Cloud Storage. 48 | - `bin/6_upload.sh` lädt die Daten in den Cloud Storage hoch. Ich bin offen für Vorschläge, wohin die Dateien noch gesichert werden können. 49 | - `bin/run.sh` ist das Bash-Script für einen kompletten Scraper-Durchlauf. 50 | - `bin/loop.sh` enthält eine Endlosschleife, die alle 10 Minuten einen Scraper-Durchlauf initiiert. 51 | - `bin/lib/config.js` enthält einen Überblick über alle Felder, inklusive einfacher Tests, ob die Felder richtig befüllt sind. 52 | - `bin/lib/helper.js` sind die kleinen Helferlein, die man so braucht. 53 | 54 | ## Beispiele 55 | 56 | Den neuesten Datenstand als "latest.ndjson.xz" runterladen: 57 | ```bash 58 | curl "https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/index.txt" | tail -n 1 | xargs -I % wget -O latest.ndjson.xz "https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/%" 59 | ``` 60 | 61 | Alle Dateien runterladen: 62 | ```bash 63 | wget -nc -r -np -l 1 -A xz https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/index.html 64 | ``` 65 | 66 | Die [gesäuberten Daten aus `2_parsed`](https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/2_parsed/index.html) kann man relativ leicht auf der Shell parsen und filtern. Beispiel: 67 | ```bash 68 | xz -dkc *.ndjson.xz | jq -r '. | select (.IdLandkreis == "09162" and .Altersgruppe == "A05-A14") | [.Geschlecht, .AnzahlFall, .NeuerFall, .MeldedatumISO, .DatenstandISO, .RefdatumISO] | @tsv' 69 | ``` 70 | 71 | Der Befehl besteht aus den folgenden Teilen: 72 | 73 | - `xz -dkc *.ndjson.xz | ` 74 | Dekomprimiere alle Dateien (`-d`), die auf `.ndjson.xz` enden und pipe die Ergebnisse (`-c`) weiter. 75 | - `jq -r '`…`'` 76 | Mit [jq](https://stedolan.github.io/jq/) kann man sehr effizient JSON verarbeiten. Die [Query- und Filtermöglichkeiten sind gut dokumentiert](https://stedolan.github.io/jq/manual/#Basicfilters). 77 | - `. | select (.IdLandkreis == "09162" and .Altersgruppe == "A05-A14") | [.Geschlecht, .AnzahlFall, .NeuerFall, .MeldedatumISO, .DatenstandISO, .RefdatumISO] | @tsv'` 78 | Alle bekannten COVID19-Fälle aus dem Stadtkreis München (`.IdLandkreis == "09162"`), mit Patient_innen im Schulalter (`.Altersgruppe == "A05-A14"`) sollen als Tab-separierte Datei (`| @tsv`) exportiert werden, mit den 6 Spalten: Geschlecht, AnzahlFall, NeuerFall, MeldedatumISO, DatenstandISO, RefdatumISO 79 | -------------------------------------------------------------------------------- /bin/1_download.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const helper = require('./lib/helper.js'); 7 | const { resolve } = require('path'); 8 | const tempFolder = resolve(__dirname, '../tmp/'); 9 | 10 | (async () => { 11 | let date = (new Date()).toISOString().slice(0, 16).replace(/[^0-9]/g, '-'); 12 | let filenameOut = resolve(__dirname, '../data/0_archived/' + date + '_dump.csv.xz'); 13 | fs.mkdirSync(tempFolder, { recursive: true }); 14 | 15 | //let filenameTmp = await scrapeAPI(); 16 | let filenameTmp = await downloadCSV(); 17 | 18 | if (filenameTmp) { 19 | // download completed 20 | fs.renameSync(filenameTmp, filenameOut); 21 | } else { 22 | // no new downloads 23 | process.exit(42); 24 | } 25 | })() 26 | 27 | async function downloadCSV() { 28 | // Quelle: https://www.arcgis.com/home/item.html?id=66876b81065340a4a48710b062319336 29 | let metadata = await helper.fetch('https://www.arcgis.com/sharing/rest/content/items/66876b81065340a4a48710b062319336?f=json'); 30 | metadata = JSON.parse(metadata); 31 | 32 | console.log(' latest: ' + (new Date(metadata.modified)).toISOString().slice(0, 16)) 33 | let lockFilename = resolve(tempFolder, metadata.modified + '.lock'); 34 | 35 | if (fs.existsSync(lockFilename)) { 36 | console.log(' already downloaded'); 37 | return false; 38 | } 39 | 40 | let redirect = await helper.fetchRedirect('https://www.arcgis.com/sharing/rest/content/items/66876b81065340a4a48710b062319336/data') 41 | 42 | console.log(' download CSV'); 43 | let buffer = await helper.fetch(redirect); 44 | 45 | console.log(' compress'); 46 | buffer = await helper.xzip(buffer); 47 | 48 | console.log(' write'); 49 | let filename = getTempFilename(); 50 | fs.writeFileSync(filename, buffer); 51 | 52 | fs.writeFileSync(lockFilename, '', 'utf8'); 53 | 54 | return filename; 55 | } 56 | 57 | async function scrapeAPI() { 58 | // not used 59 | // but we may need that function when CSV download is not available 60 | // data status: https://npgeo-corona-npgeo-de.hub.arcgis.com/datasets/38e0356be30642868b4c526424102718_0/explore 61 | 62 | 63 | let filename = getTempFilename(); 64 | 65 | let page = 0; 66 | let pageSize = 5000; 67 | let count = 0; 68 | let data; 69 | let step = 0; 70 | let xz = helper.lineXzipWriter(filename); 71 | 72 | do { 73 | if (step % 5 === 0) process.stderr.write('·'); 74 | step++; 75 | 76 | let url = 'https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_COVID19/FeatureServer/0/query?where=1%3D1&outFields=*&orderByFields=ObjectId%20ASC&resultOffset=' + (page * pageSize) + '&resultRecordCount=' + pageSize + '&f=json'; 77 | data = await helper.fetch(url); 78 | try { 79 | data = JSON.parse(data); 80 | let line = JSON.stringify(data); // single line 81 | await xz.write(line); 82 | } catch (e) { 83 | console.log(url); 84 | console.log(data); 85 | throw e; 86 | } 87 | count += ((data || {}).features || []).length || 0; 88 | page++; 89 | } while (data.exceededTransferLimit) 90 | 91 | process.stderr.write(' ' + count + '\n'); 92 | 93 | console.log(' close') 94 | await xz.close(); 95 | 96 | return filename; 97 | } 98 | 99 | function getTempFilename() { 100 | return resolve(tempFolder, (new Date()).toISOString().replace(/[^0-9]+/g, '_') + '.tmp'); 101 | } 102 | -------------------------------------------------------------------------------- /bin/2_deduplicate.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const { resolve, dirname } = require('path'); 7 | const crypto = require('crypto'); 8 | 9 | 10 | 11 | const dirSrc = resolve(__dirname, '../data/0_archived/'); 12 | const hashCacheFilename = resolve(__dirname, '../tmp/hashes.json'); 13 | fs.mkdirSync(dirname(hashCacheFilename), { recursive: true }) 14 | let hashCache = new Map(); 15 | if (fs.existsSync(hashCacheFilename)) hashCache = new Map(JSON.parse(fs.readFileSync(hashCacheFilename))); 16 | 17 | 18 | let files = []; 19 | fs.readdirSync(dirSrc).sort().forEach(filename => { 20 | if (!filename.endsWith('.xz')) return; 21 | 22 | 23 | let fullname = resolve(dirSrc, filename); 24 | let key = filename + ':' + fs.statSync(fullname).size; 25 | 26 | let hash; 27 | if (hashCache.has(key)) { 28 | hash = hashCache.get(key); 29 | } else { 30 | hash = crypto.createHash('sha256').update(fs.readFileSync(fullname)).digest('hex'); 31 | hashCache.set(key, hash); 32 | } 33 | 34 | files.push({ fullname, hash }); 35 | }) 36 | 37 | files.sort((a, b) => a.hash.localeCompare(b.hash) || a.fullname.localeCompare(b.fullname)); 38 | 39 | let lastHash = false; 40 | files = files.filter(f => lastHash === (lastHash = f.hash)); 41 | 42 | files.forEach(f => fs.rmSync(f.fullname)); 43 | 44 | fs.writeFileSync(hashCacheFilename, JSON.stringify(Array.from(hashCache.entries()))); 45 | -------------------------------------------------------------------------------- /bin/3_parse.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const helper = require('./lib/helper.js'); 7 | const config = require('./lib/config.js'); 8 | const { resolve, basename } = require('path'); 9 | 10 | const pathIn = resolve(__dirname, '../data/0_archived'); 11 | const pathOut = resolve(__dirname, '../data/2_parsed'); 12 | 13 | let filesIn = fs.readdirSync(pathIn).filter(f => f.endsWith('.xz')); 14 | 15 | (async () => { 16 | let xz; 17 | 18 | for (let fileIn of filesIn) { 19 | let timestamp = fileIn.match(/\d\d\d\d-\d\d-\d\d-\d\d-\d\d/); 20 | if (!timestamp) throw Error(); 21 | 22 | let fileOut = `data_${timestamp[0]}.ndjson.xz`; 23 | 24 | let filenameIn = resolve(pathIn, fileIn); 25 | let filenameOut = resolve(pathOut, fileOut); 26 | let filenameTmp = resolve(__dirname, '../tmp/' + (new Date()).toISOString() + '.tmp'); 27 | fs.mkdirSync(resolve(__dirname, '../tmp/'), { recursive: true }); 28 | 29 | if (fs.existsSync(filenameOut)) continue; 30 | 31 | console.log('parsing ' + fileIn); 32 | 33 | let type = fileIn.replace(timestamp, '?'); 34 | xz = helper.lineXzipWriter(filenameTmp); 35 | 36 | switch (type) { 37 | case '?_api_raw.json.xz': 38 | await openJSONApiRaw(filenameIn, parseEntry); 39 | break; 40 | case '?_api_raw.ndjson.xz': 41 | await openNDJSONApiRaw(filenameIn, parseEntry); 42 | break; 43 | case '?_dump.csv.xz': 44 | await openCsvDump(filenameIn, parseEntry); 45 | break; 46 | default: throw Error(`unknown type "${type}"`) 47 | } 48 | 49 | await xz.close(); 50 | fs.renameSync(filenameTmp, filenameOut); 51 | } 52 | 53 | async function parseEntry(entry) { 54 | cleanupDates(entry); 55 | checkEntry(entry); 56 | await xz.write(JSON.stringify(entry)); 57 | } 58 | })() 59 | 60 | async function openJSONApiRaw(filenameIn, cbEntry) { 61 | console.log(' load'); 62 | let data = await fs.promises.readFile(filenameIn); 63 | 64 | console.log(' decompress'); 65 | data = await helper.xunzip(data); 66 | 67 | console.log(' parse'); 68 | data = JSON.parse(data); 69 | 70 | data = data.map(b => b.features.map(e => e.attributes)); 71 | data = [].concat.apply([], data); 72 | 73 | for (let entry of data) await cbEntry(entry); 74 | } 75 | 76 | async function openNDJSONApiRaw(filenameIn, cbEntry) { 77 | for await (let line of helper.lineXzipReader(filenameIn)) { 78 | line = JSON.parse(line); 79 | for (let feature of line.features) { 80 | await cbEntry(feature.attributes); 81 | } 82 | } 83 | } 84 | 85 | async function openCsvDump(filenameIn, cbEntry) { 86 | let converter; 87 | for await (let line of helper.lineXzipReader(filenameIn)) { 88 | if (line.charCodeAt(0) > 200) line = line.slice(1); 89 | if (line.endsWith('\r')) line = line.slice(0, line.length - 1); 90 | if (line.length === 0) return; 91 | 92 | let quoteCount = (line.match(/\"/g) || []).length; 93 | if (quoteCount === 2) { 94 | line = line.replace(/\".*\"/, t => t.replace(/[\",;]+/g, '')); 95 | } else if (quoteCount !== 0) throw Error(JSON.stringify(line)); 96 | 97 | 98 | if (!converter) { 99 | converter = getConverter(line, filenameIn); 100 | continue; 101 | } 102 | 103 | await cbEntry(converter(line)); 104 | } 105 | 106 | function getConverter(header, filename) { 107 | if (header === 'IdBundesland,Bundesland,IdLandkreis,Landkreis,Altersgruppe,Altersgruppe2,Geschlecht,Meldedatum,Refdatum,IstErkrankungsbeginn,NeuerFall,NeuerTodesfall,NeuGenesen,AnzahlFall,AnzahlTodesfall,AnzahlGenesen,Datenstand') { 108 | return line => { 109 | line = line.split(','); 110 | if (line.length !== 17) { 111 | console.log(line) 112 | throw Error('line to short') 113 | } 114 | return { 115 | IdBundesland: parseInt(line[0], 10), 116 | Bundesland: line[1], 117 | IdLandkreis: fixIdLandkreis(line[2]), 118 | Landkreis: line[3], 119 | Altersgruppe: line[4], 120 | Geschlecht: line[6], 121 | Meldedatum: line[7], 122 | Refdatum: line[8], 123 | IstErkrankungsbeginn: parseInt(line[9], 10), 124 | NeuerFall: parseInt(line[10], 10), 125 | NeuerTodesfall: parseInt(line[11], 10), 126 | NeuGenesen: parseInt(line[12], 10), 127 | AnzahlFall: parseInt(line[13], 10), 128 | AnzahlTodesfall: parseInt(line[14], 10), 129 | AnzahlGenesen: parseInt(line[15], 10), 130 | Datenstand: line[16], 131 | } 132 | } 133 | } 134 | if (header === 'IdLandkreis,Altersgruppe,Geschlecht,Meldedatum,Refdatum,IstErkrankungsbeginn,NeuerFall,NeuerTodesfall,NeuGenesen,AnzahlFall,AnzahlTodesfall,AnzahlGenesen') { 135 | let Datenstand = basename(filename).slice(0, 10); 136 | let landkreisLookup = fs.readFileSync(resolve(__dirname, '../data/landkreise.json'), 'utf8'); 137 | landkreisLookup = new Map(JSON.parse(landkreisLookup).map(l => [l.IdLandkreis, l])) 138 | 139 | return line => { 140 | line = line.split(','); 141 | if (line.length !== 12) { 142 | console.log(line) 143 | throw Error('line to short') 144 | } 145 | let IdLandkreis = fixIdLandkreis(line[0]); 146 | let landkreis = landkreisLookup.get(IdLandkreis); 147 | if (!landkreis) { 148 | console.log({ IdLandkreis }); 149 | throw Error() 150 | } 151 | 152 | return { 153 | IdBundesland: landkreis.IdBundesland, 154 | Bundesland: landkreis.Bundesland, 155 | IdLandkreis, 156 | Landkreis: landkreis.Landkreis, 157 | Altersgruppe: line[1], 158 | Geschlecht: line[2], 159 | Meldedatum: line[3], 160 | Refdatum: line[4], 161 | IstErkrankungsbeginn: parseInt(line[5], 10), 162 | NeuerFall: parseInt(line[6], 10), 163 | NeuerTodesfall: parseInt(line[7], 10), 164 | NeuGenesen: parseInt(line[8], 10), 165 | AnzahlFall: parseInt(line[9], 10), 166 | AnzahlTodesfall: parseInt(line[10], 10), 167 | AnzahlGenesen: parseInt(line[11], 10), 168 | Datenstand, 169 | } 170 | } 171 | } 172 | 173 | console.log({ header }); 174 | throw Error('unknown header'); 175 | 176 | function fixIdLandkreis(id) { 177 | return (id === '0-1') ? '-1' : id; 178 | } 179 | } 180 | } 181 | 182 | function checkEntry(obj) { 183 | let keyList = Object.keys(obj); 184 | 185 | let keysLookup = new Set(keyList); 186 | 187 | keyList.forEach(key => { 188 | if (obj[key] === undefined) { 189 | delete obj[key]; 190 | return; 191 | } 192 | if (!config.checkField(key, obj[key])) error('field check failed: key "' + key + '", value "' + obj[key] + '"'); 193 | }); 194 | 195 | config.mandatoryList.forEach(keyMandatory => { 196 | if (!keysLookup.has(keyMandatory)) error('mandatory key missing: "' + keyMandatory + '" in Object "' + JSON.stringify(obj) + '"'); 197 | keysLookup.delete(keyMandatory); 198 | }) 199 | 200 | Array.from(keysLookup.keys()).forEach(key => { 201 | if (!config.optionalSet.has(key)) error('key is not known: "' + key + '"'); 202 | }) 203 | 204 | function error(text) { 205 | console.error(text); 206 | throw Error(); 207 | } 208 | } 209 | 210 | function cleanupDates(obj) { 211 | obj.MeldedatumISO = fixDate(obj.Meldedatum); 212 | obj.DatenstandISO = fixDate(obj.Datenstand); 213 | obj.RefdatumISO = fixDate(obj.Refdatum); 214 | 215 | function fixDate(value) { 216 | if (!value) return undefined; 217 | 218 | let result = value; 219 | switch (typeof value) { 220 | case 'string': 221 | if (/^\d{8}00000$/.test(result)) { 222 | result = parseInt(result, 10); 223 | break; 224 | } 225 | 226 | if (/^\d{1,2}\/\d{1,2}\/20\d\d 12:00:00 AM$/.test(result)) { 227 | result = Date.parse(result); 228 | break; 229 | } 230 | 231 | if (/^20\d\d\/\d{2}\/\d{2} 00:00:00$/.test(result)) { 232 | result = Date.parse(result); 233 | break; 234 | } 235 | 236 | if (/^\d\d\.\d\d\.20\d\d,? 00:00( Uhr)?$/.test(result)) { 237 | result = result.split(/[^0-9]+/); 238 | result = result[2] + '-' + result[1] + '-' + result[0] + 'T00:00:00Z'; 239 | } 240 | 241 | if (/^20\d\d-\d\d-\d\d$/.test(result)) result += 'T00:00:00Z'; 242 | 243 | if (/^20\d\d-\d\d-\d\d(T| )00:00:00(\.000)?(Z|\+00:00)$/.test(result)) { 244 | result = Date.parse(result); 245 | break; 246 | } 247 | 248 | throw Error('unknown date format "' + value + '" (' + result + ')'); 249 | break; 250 | case 'number': 251 | // range check 252 | if (result < 1577836800000) throw Error(); 253 | if (result > Date.now()) throw Error(); 254 | break; 255 | default: throw Error(JSON.stringify(value)); 256 | } 257 | result = new Date(result + 43200000); 258 | result = result.toISOString(); 259 | return result.slice(0, 10); 260 | } 261 | } -------------------------------------------------------------------------------- /bin/4_check.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const helper = require('./lib/helper.js'); 7 | const { resolve, relative } = require('path'); 8 | 9 | const base = resolve(__dirname, '../data/'); 10 | const path0 = resolve(base, '0_archived'); 11 | const path1 = resolve(base, '1_ignored'); 12 | const path2 = resolve(base, '2_parsed'); 13 | const path4 = resolve(base, 'z_4_overview'); 14 | 15 | fs.mkdirSync(path4, { recursive: true }); 16 | 17 | const files0 = scanFolder(path0); 18 | const files2 = scanFolder(path2); 19 | 20 | (async () => { 21 | console.log(' archived, not parsed'); 22 | minus(files0, files2).forEach(f => console.log('mv "' + relative(base, f.fullname) + '" "' + relative(base, path1) + '"')); 23 | 24 | console.log(' parsed, not archived'); 25 | minus(files2, files0).forEach(f => console.log('rm "' + relative(base, f.fullname) + '"')); 26 | 27 | console.log(' check sums in parsed'); 28 | await addSums(files2); 29 | 30 | if (!sanityCheck(files2)) { 31 | process.exit(1); 32 | console.log('errors found'); 33 | } 34 | })() 35 | 36 | function scanFolder(path) { 37 | let files = fs.readdirSync(path).filter(f => f.endsWith('.xz')); 38 | files = files.map(filename => { 39 | let timestamp = filename.match(/\d\d\d\d-\d\d-\d\d-\d\d-\d\d/)[0]; 40 | if (!timestamp) throw Error(); 41 | 42 | let fullname = resolve(path, filename) 43 | 44 | return { 45 | filename, 46 | fullname, 47 | timestamp, 48 | day: timestamp.slice(0, 10), 49 | size: fs.statSync(fullname).size 50 | } 51 | }) 52 | files = files.sort((a, b) => a.filename < b.filename ? -1 : 1); 53 | return files; 54 | } 55 | 56 | function minus(list1, list2) { 57 | list2 = new Set(list2.map(f => f.timestamp)); 58 | list1 = list1.filter(f => !list2.has(f.timestamp)); 59 | return list1; 60 | } 61 | 62 | function sanityCheck(files) { 63 | let noErrors = true; 64 | let lastCaseCount = 0; 65 | let lastEntryCount = -1; 66 | let lastFilename = -1; 67 | 68 | files.forEach(file => { 69 | let errors = []; 70 | 71 | 72 | if (file.filename > 'data_2022-04-11') { 73 | if (file.caseCount < lastCaseCount - 10) errors.push('- less cases???'); 74 | if (file.caseCount > lastCaseCount + 500000) errors.push('- way too much cases'); 75 | 76 | if (file.entryCount < lastEntryCount - 10000) errors.push('- less entries???'); 77 | if (file.entryCount > lastEntryCount + 100000) errors.push('- way too much entries'); 78 | } 79 | 80 | if (errors.length > 0) { 81 | console.log('CHECK ERROR'); 82 | console.log(errors.join('\n')); 83 | console.table([ 84 | { filename: lastFilename, entryCount: lastEntryCount, caseCount: lastCaseCount }, 85 | { filename: file.filename, entryCount: file.entryCount, caseCount: file.caseCount }, 86 | { filename: 'diff', entryCount: file.entryCount - lastEntryCount, caseCount: file.caseCount - lastCaseCount } 87 | ]) 88 | noErrors = false; 89 | } 90 | 91 | lastCaseCount = file.caseCount; 92 | lastEntryCount = file.entryCount; 93 | lastFilename = file.filename; 94 | }); 95 | 96 | return noErrors; 97 | } 98 | 99 | async function addSums(files) { 100 | for (let file of files) { 101 | let info = await getFileInfo(file); 102 | file.caseCount = info.caseCount; 103 | file.entryCount = info.entryCount; 104 | } 105 | 106 | async function getFileInfo(file) { 107 | let cacheFile = resolve(path4, file.timestamp + '.json'); 108 | 109 | if (fs.existsSync(cacheFile)) return JSON.parse(fs.readFileSync(cacheFile)) 110 | 111 | console.log(' scan ' + file.filename); 112 | 113 | let entryCount = 0; 114 | let caseCount = 0; 115 | for await (let line of helper.lineXzipReader(file.fullname)) { 116 | line = JSON.parse(line); 117 | if (line.AnzahlFall > 0) caseCount += line.AnzahlFall; 118 | entryCount++; 119 | } 120 | let data = { entryCount, caseCount }; 121 | fs.writeFileSync(cacheFile, JSON.stringify(data)) 122 | 123 | return data; 124 | } 125 | } 126 | -------------------------------------------------------------------------------- /bin/5_index_data.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const { resolve } = require('path'); 7 | 8 | const cloudUrl = 'https://storage.googleapis.com/brdata-public-data/rki-corona-archiv/'; 9 | 10 | generateIndex('0_archived'); 11 | generateIndex('1_ignored'); 12 | generateIndex('2_parsed'); 13 | 14 | function generateIndex(dir) { 15 | let fullDir = resolve(__dirname, '../data/', dir); 16 | let result = []; 17 | 18 | fs.readdirSync(fullDir).forEach(f => { 19 | let stat = fs.statSync(resolve(fullDir, f)); 20 | if (stat.isDirectory()) return; 21 | if (!f.endsWith('.xz')) return; 22 | result.push({ 23 | url: cloudUrl + dir + '/' + f, 24 | name: f, 25 | size: Math.round(stat.size / 1024).toString().replace(/\B(?=(\d{3})+(?!\d))/g, "'") + ' KB', 26 | }); 27 | }) 28 | 29 | result.sort(); 30 | 31 | fs.writeFileSync(resolve(fullDir, 'index.txt'), result.map(f => f.name).join('\n')); 32 | 33 | let html = result.map(f => '' + f.name + ' ' + f.size).join('
\n'); 34 | html = '' + html + ''; 35 | 36 | fs.writeFileSync(resolve(fullDir, 'index.html'), html); 37 | } 38 | -------------------------------------------------------------------------------- /bin/6_upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | cd "$(dirname "$0")" 5 | 6 | echo "upload" 7 | 8 | gsutil rsync -C -d -e -x '(?!.*\.(xz|txt|html))' ../data/0_archived/ gs://brdata-public-data/rki-corona-archiv/0_archived/ 2>&1 9 | gsutil rsync -C -d -e -x '(?!.*\.(xz|txt|html))' ../data/1_ignored/ gs://brdata-public-data/rki-corona-archiv/1_ignored/ 2>&1 10 | gsutil rsync -C -d -e -x '(?!.*\.(xz|txt|html))' ../data/2_parsed/ gs://brdata-public-data/rki-corona-archiv/2_parsed/ 2>&1 11 | -------------------------------------------------------------------------------- /bin/7_recompress.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | "use strict" 4 | 5 | const fs = require('fs'); 6 | const child_process = require('child_process'); 7 | const { resolve } = require('path'); 8 | 9 | const lookback = 80; 10 | 11 | if ((new Date()).getHours() >= 10) { 12 | // recompress only in the evening after 20:00 13 | check('0_archived'); 14 | check('2_parsed'); 15 | } 16 | 17 | process.exit(42); 18 | 19 | function check(folder) { 20 | let fullFolder = resolve(__dirname, '../data', folder); 21 | 22 | // scan for files 23 | let files = fs.readdirSync(fullFolder); 24 | files = files.filter(f => f.endsWith('.xz')); 25 | files.sort(); 26 | files = files.slice(-lookback); 27 | files = files.map(filename => { 28 | let fullname = resolve(fullFolder, filename); 29 | let size = fs.statSync(fullname).size; 30 | return { filename, fullname, size } 31 | }) 32 | 33 | // linear regression of file sizes 34 | let sx = 0, sxx = 0, sxy = 0, sy = 0; 35 | files.map((f, x) => { 36 | let y = f.size; 37 | sx += x; 38 | sxx += x * x; 39 | sxy += x * y; 40 | sy += y; 41 | }); 42 | 43 | let n = files.length; 44 | let w = n * sxx - sx * sx; 45 | let a = (sy * sxx - sx * sxy) / w; 46 | let b = (n * sxy - sx * sy) / w; 47 | 48 | files.forEach((f, x) => f.diff = f.size - (a + b * x)); 49 | 50 | // max diff 51 | files.sort((a, b) => b.diff - a.diff); 52 | let worstFile = files[0]; 53 | //console.log('worst file diff', (worstFile.diff/1024).toFixed(0), 'KB'); 54 | 55 | if (worstFile.diff < 5e5) return // everything is ok 56 | 57 | recompress(worstFile.fullname); 58 | 59 | process.exit(); 60 | } 61 | 62 | function recompress(fullname) { 63 | console.log(' recompress', fullname); 64 | 65 | const tempFolder = resolve(__dirname, '../tmp'); 66 | fs.mkdirSync(tempFolder, { recursive: true }) 67 | 68 | const tempFullname = resolve(tempFolder, Math.random().toString(36).slice(2)); 69 | 70 | try { 71 | child_process.execSync(`nice -20 xz -dkcq "${fullname}" | xz -z9eq > "${tempFullname}"`); 72 | 73 | fs.renameSync(tempFullname, fullname); 74 | } catch (e) { 75 | 76 | } 77 | 78 | process.exit(42); 79 | } 80 | -------------------------------------------------------------------------------- /bin/lib/config.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const fields = [ 4 | { name: 'ObjectId', mandatory: false, check: v => (typeof v === 'number') }, 5 | { name: 'IdBundesland', mandatory: true, check: v => (typeof v === 'number') && /^(\-1|\d+)$/.test(v) }, 6 | { name: 'Bundesland', mandatory: true, check: v => (typeof v === 'string') }, 7 | { name: 'IdLandkreis', mandatory: true, check: v => (typeof v === 'string') && /^(\-1|\d{4,5})$/.test(v) }, 8 | { name: 'Landkreis', mandatory: true, check: v => (typeof v === 'string') }, 9 | { name: 'Altersgruppe', mandatory: true, check: v => (typeof v === 'string') }, 10 | { name: 'Altersgruppe2', mandatory: false, check: v => (typeof v === 'string') }, 11 | { name: 'Geschlecht', mandatory: true, check: v => (typeof v === 'string') }, 12 | { name: 'AnzahlFall', mandatory: true, check: v => (typeof v === 'number') }, 13 | { name: 'AnzahlTodesfall', mandatory: true, check: v => (typeof v === 'number') }, 14 | { name: 'AnzahlGenesen', mandatory: false, check: v => (typeof v === 'number') }, 15 | { name: 'NeuerFall', mandatory: false, check: v => (typeof v === 'number') }, 16 | { name: 'NeuerTodesfall', mandatory: false, check: v => (typeof v === 'number') }, 17 | { name: 'NeuGenesen', mandatory: false, check: v => (typeof v === 'number') }, 18 | { name: 'Refdatum', mandatory: false, check: v => (typeof v === 'string') || (typeof v === 'number') }, 19 | { name: 'Meldedatum', mandatory: true, check: v => (typeof v === 'string') || (typeof v === 'number') }, 20 | { name: 'Datenstand', mandatory: true, check: v => (typeof v === 'string') }, 21 | { name: 'IstErkrankungsbeginn', mandatory: false, check: v => (typeof v === 'number') }, 22 | { name: 'RefdatumISO', mandatory: false, check: v => (typeof v === 'string') }, 23 | { name: 'MeldedatumISO', mandatory: true, check: v => (typeof v === 'string') }, 24 | { name: 'DatenstandISO', mandatory: true, check: v => (typeof v === 'string') }, 25 | ]; 26 | 27 | const lookupCheck = new Map(fields.map(f => [f.name, f.check])); 28 | 29 | module.exports = { 30 | fields, 31 | checkField: (f, v) => lookupCheck.get(f)(v), 32 | fieldList: fields.map(f => f.name), 33 | mandatoryList: fields.filter(f => f.mandatory).map(f => f.name), 34 | optionalSet: new Set(fields.filter(f => !f.mandatory).map(f => f.name)), 35 | } -------------------------------------------------------------------------------- /bin/lib/helper.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | const child_process = require('child_process'); 4 | const fs = require('fs'); 5 | const https = require('https'); 6 | const zlib = require('zlib'); 7 | 8 | var helper = module.exports = { 9 | bzip2, bunzip2, 10 | fetch, 11 | fetchRedirect, 12 | gzip, gunzip, 13 | xzip, xunzip, 14 | lineXzipReader, lineXzipWriter, 15 | runParallel, 16 | lineGzipReader, lineGzipWriter, 17 | encodeTSV, encodeCSV, 18 | slowDown, logPercent, 19 | } 20 | 21 | function logPercent() { 22 | return slowDown(v => console.log((100 * v).toFixed(1))); 23 | } 24 | 25 | function fetch(url) { 26 | return new Promise((resolve, reject) => { 27 | https.get(url, response => { 28 | let buf = []; 29 | response.on('data', data => buf.push(data)); 30 | response.on('end', () => resolve(Buffer.concat(buf))); 31 | response.on('error', data => buf.push(data)); 32 | if (response.statusCode !== 200) { 33 | console.log(response); 34 | throw Error(); 35 | } 36 | }).on('error', error => { 37 | throw Error(error) 38 | }) 39 | }); 40 | } 41 | 42 | function fetchRedirect(url) { 43 | return new Promise((resolve, reject) => { 44 | https.get(url, response => { 45 | if (response.statusCode !== 302) { 46 | console.log(response); 47 | throw Error(); 48 | } 49 | return resolve(response.headers.location); 50 | }).on('error', error => { 51 | throw Error(error) 52 | }) 53 | }); 54 | } 55 | 56 | async function* lineGzipReader(filename, cb) { 57 | const gz = child_process.spawn('gz', ['-dck', filename]); 58 | 59 | let buffer = Buffer.alloc(0); 60 | for await (let block of gz.stdout) { 61 | buffer = Buffer.concat([buffer, block]); 62 | 63 | let pos, lastPos = 0; 64 | while ((pos = buffer.indexOf(10, lastPos)) >= 0) { 65 | yield buffer.slice(lastPos, pos).toString(); 66 | lastPos = pos + 1; 67 | } 68 | buffer = buffer.slice(lastPos); 69 | } 70 | if (buffer.length > 0) yield buffer.toString(); 71 | } 72 | 73 | function lineGzipWriter(filename) { 74 | let finished = false; 75 | let block = [], blockSize = 0; 76 | let file = fs.createWriteStream(filename); 77 | let gzip = zlib.createGzip({ level: 9 }); 78 | gzip.pipe(file); 79 | 80 | async function write(line) { 81 | if (finished) throw Error(); 82 | if (line === undefined) { 83 | await flush(); 84 | await close(); 85 | finished = true; 86 | } else { 87 | block.push(line + '\n'); 88 | blockSize += line.length; 89 | if (blockSize > 1e5) await flush(); 90 | } 91 | } 92 | 93 | async function flush() { 94 | let buf = Buffer.from(block.join('')); 95 | block = []; 96 | blockSize = 0; 97 | return new Promise(res => gzip.write(buf, res)) 98 | } 99 | 100 | async function close() { 101 | return new Promise(res => { 102 | file.once('close', res); 103 | gzip.end(); 104 | }) 105 | } 106 | 107 | return write; 108 | } 109 | 110 | function bzip2(bufIn) { 111 | if (typeof bufIn === 'string') bufIn = Buffer.from(bufIn, 'utf8'); 112 | return runCommand('bzip2', ['-zck9'], bufIn); 113 | } 114 | 115 | function bunzip2(bufIn) { 116 | return runCommand('bzip2', ['-dck'], bufIn); 117 | } 118 | 119 | function gzip(bufIn) { 120 | if (typeof bufIn === 'string') bufIn = Buffer.from(bufIn, 'utf8'); 121 | return new Promise(res => zlib.gzip(bufIn, { level: 9 }, (err, bufOut) => res(bufOut))) 122 | } 123 | 124 | function gunzip(bufIn) { 125 | return new Promise(res => zlib.gunzip(bufIn, (err, bufOut) => res(bufOut))) 126 | } 127 | 128 | function xzip(bufIn) { 129 | if (typeof bufIn === 'string') bufIn = Buffer.from(bufIn, 'utf8'); 130 | return runCommand('xz', ['-zck9e'], bufIn); 131 | } 132 | 133 | function xunzip(bufIn) { 134 | return runCommand('xz', ['-dck'], bufIn); 135 | } 136 | 137 | async function* lineXzipReader(filename) { 138 | const filesize = fs.statSync(filename).size; 139 | let filepos = 0; 140 | const time0 = Date.now(); 141 | const file = fs.createReadStream(filename); 142 | file.on('data', chunk => { 143 | filepos += chunk.length; 144 | let time = Date.now(); 145 | let p = filepos / filesize; 146 | time = (time - time0) / p * (1 - p); 147 | process.stderr.write('\u001b[2K\r\t' + (100 * p).toFixed(2) + '%\t' + (time / 60000).toFixed(1) + 'min') 148 | }) 149 | const xz = child_process.spawn('xz', ['-d']); 150 | file.pipe(xz.stdin); 151 | 152 | let buffer = Buffer.alloc(0); 153 | for await (let block of xz.stdout) { 154 | //console.log(block.length); 155 | buffer = Buffer.concat([buffer, block]); 156 | 157 | let pos, lastPos = 0; 158 | while ((pos = buffer.indexOf(10, lastPos)) >= 0) { 159 | yield buffer.slice(lastPos, pos).toString(); 160 | lastPos = pos + 1; 161 | } 162 | buffer = buffer.slice(lastPos); 163 | } 164 | if (buffer.length > 0) yield buffer.toString(); 165 | process.stderr.write('\n') 166 | } 167 | 168 | function lineXzipWriter(filename) { 169 | let finished = false; 170 | let block = [], blockSize = 0; 171 | let xz = child_process.spawn('xz', ['-zck9e']); 172 | let file = fs.createWriteStream(filename); 173 | xz.stdout.pipe(file); 174 | 175 | async function write(line) { 176 | if (finished) throw Error(); 177 | 178 | block.push(line + '\n'); 179 | blockSize += line.length; 180 | if (blockSize > 1e5) await flush(); 181 | } 182 | 183 | async function flush() { 184 | let buf = Buffer.from(block.join('')); 185 | block = []; 186 | blockSize = 0; 187 | return new Promise(res => xz.stdin.write(buf, res)) 188 | } 189 | 190 | async function close() { 191 | if (finished) throw Error(); 192 | 193 | await flush(); 194 | finished = true; 195 | 196 | return new Promise(res => { 197 | xz.once('close', res); 198 | xz.stdin.end(); 199 | }) 200 | } 201 | 202 | return { write, close }; 203 | } 204 | 205 | function runCommand(cmd, args, bufIn) { 206 | return new Promise((resolve, reject) => { 207 | let bufOut = []; 208 | let p = child_process.spawn(cmd, args); 209 | p.stdin.end(bufIn); 210 | p.stdout.on('data', chunk => bufOut.push(chunk)); 211 | p.stdout.on('end', () => resolve(Buffer.concat(bufOut)));; 212 | p.on('error', err => { 213 | throw err; 214 | reject(); 215 | }) 216 | }) 217 | } 218 | 219 | function runParallel(limit, list) { 220 | return new Promise((resolve, reject) => { 221 | let active = 0; 222 | let index = 0; 223 | let finished = false 224 | next(); 225 | function next() { 226 | if ((active === 0) && (index >= list.length) && !finished) { 227 | finished = true; 228 | return resolve() 229 | } 230 | while ((active < limit) && (index < list.length)) { 231 | let entry = list[index]; 232 | index++; 233 | if (!entry) continue; 234 | active++; 235 | entry().then(() => { 236 | active--; 237 | next() 238 | }, reject) 239 | } 240 | } 241 | }) 242 | } 243 | 244 | function slowDown(cb, delay) { 245 | if (!cb) throw Error(); 246 | if (!delay) delay = 3000; 247 | let nextUpdate = Date.now(); 248 | return v => { 249 | let now = Date.now(); 250 | if (now < nextUpdate) return; 251 | nextUpdate += delay; 252 | cb(v); 253 | } 254 | } 255 | 256 | function encodeTSV(list) { 257 | let keys = new Set(); 258 | list.forEach(e => Object.keys(e).forEach(k => keys.add(k))); 259 | keys = Array.from(keys.values()); 260 | list = list.map(e => keys.map(k => e[k]).join('\t')); 261 | list.unshift(keys.join('\t')); 262 | return list.join('\n'); 263 | } 264 | 265 | function encodeCSV(list) { 266 | let keys = new Set(); 267 | list.forEach(e => Object.keys(e).forEach(k => keys.add(k))); 268 | keys = Array.from(keys.values()); 269 | list = list.map(e => keys.map(k => { 270 | let v = '' + e[k]; 271 | return v.includes(',') ? '"' + v + '"' : v; 272 | }).join(',')); 273 | list.unshift(keys.join(',')); 274 | return list.join('\n'); 275 | } 276 | -------------------------------------------------------------------------------- /bin/loop.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | while true; do 6 | echo "start run at $(date '+%Y-%m-%d %H:%M:%S')" 7 | SECONDS=0 8 | 9 | if [ -f ~/projects/notificato/notificato.js ]; then 10 | node ~/projects/notificato/notificato.js "Corona Scraper" ./run.sh || true 11 | else 12 | ./run.sh || true 13 | fi 14 | 15 | printf " took %02d:%02d:%02d\n" "$((SECONDS / 3600 % 24))" "$((SECONDS / 60 % 60))" "$((SECONDS % 60))" 16 | 17 | sleep 600 18 | done 19 | -------------------------------------------------------------------------------- /bin/recompress.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "helper script to recompress files in place" 4 | 5 | set -e 6 | 7 | bin_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 8 | tmp_dir="$(cd "$(dirname "$bin_dir")"/tmp && pwd)" 9 | src_dir="$(pwd)" 10 | dst_dir="$(pwd)" 11 | 12 | for filename in "$@"; do 13 | src_file="$src_dir"/"$filename" 14 | tmp_file="$tmp_dir"/"$filename" 15 | dst_file="$dst_dir"/"$filename" 16 | 17 | echo "recompress $filename" 18 | 19 | nice -20 xz -dkcq $src_file | xz -z9eq > $tmp_file 20 | mv -f $tmp_file $dst_file 21 | done 22 | -------------------------------------------------------------------------------- /bin/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cd "$(dirname "$0")" 4 | 5 | set -e # exit on error 6 | #set -x # print commands 7 | 8 | git pull -q 9 | 10 | { 11 | node 1_download.js \ 12 | && node 2_deduplicate.js \ 13 | && node 3_parse.js \ 14 | && node 4_check.js 15 | } || { 16 | error=$? 17 | 18 | if [ $error -eq 42 ]; then 19 | echo "no new data" 20 | # node 7_recompress.js || exit 0 21 | else 22 | echo "ERROR happend $error" 23 | exit $error 24 | fi 25 | } 26 | 27 | node 5_index_data.js 28 | 29 | uploadResults=$({ bash 6_upload.sh | grep "Copying file" | grep -v "index"; }) || true 30 | 31 | if [[ "$uploadResults" == "" ]]; then 32 | echo "no new files, thx, bye" 33 | exit 0 34 | fi 35 | 36 | echo "$uploadResults" 37 | exit 42 38 | -------------------------------------------------------------------------------- /data/landkreise.json: -------------------------------------------------------------------------------- 1 | [ 2 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1001", "Landkreis":"SK Flensburg" }, 3 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1002", "Landkreis":"SK Kiel" }, 4 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1003", "Landkreis":"SK Lübeck" }, 5 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1004", "Landkreis":"SK Neumünster" }, 6 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1051", "Landkreis":"LK Dithmarschen" }, 7 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1053", "Landkreis":"LK Herzogtum Lauenburg" }, 8 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1054", "Landkreis":"LK Nordfriesland" }, 9 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1055", "Landkreis":"LK Ostholstein" }, 10 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1056", "Landkreis":"LK Pinneberg" }, 11 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1057", "Landkreis":"LK Plön" }, 12 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1058", "Landkreis":"LK Rendsburg-Eckernförde" }, 13 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1059", "Landkreis":"LK Schleswig-Flensburg" }, 14 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1060", "Landkreis":"LK Segeberg" }, 15 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1061", "Landkreis":"LK Steinburg" }, 16 | { "IdBundesland":1, "Bundesland":"Schleswig-Holstein", "IdLandkreis":"1062", "Landkreis":"LK Stormarn" }, 17 | { "IdBundesland":2, "Bundesland":"Hamburg", "IdLandkreis":"2000", "Landkreis":"SK Hamburg" }, 18 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3101", "Landkreis":"SK Braunschweig" }, 19 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3102", "Landkreis":"SK Salzgitter" }, 20 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3103", "Landkreis":"SK Wolfsburg" }, 21 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3151", "Landkreis":"LK Gifhorn" }, 22 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3153", "Landkreis":"LK Goslar" }, 23 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3154", "Landkreis":"LK Helmstedt" }, 24 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3155", "Landkreis":"LK Northeim" }, 25 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3157", "Landkreis":"LK Peine" }, 26 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3158", "Landkreis":"LK Wolfenbüttel" }, 27 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3159", "Landkreis":"LK Göttingen" }, 28 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3241", "Landkreis":"Region Hannover" }, 29 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3251", "Landkreis":"LK Diepholz" }, 30 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3252", "Landkreis":"LK Hameln-Pyrmont" }, 31 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3254", "Landkreis":"LK Hildesheim" }, 32 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3255", "Landkreis":"LK Holzminden" }, 33 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3256", "Landkreis":"LK Nienburg (Weser)" }, 34 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3257", "Landkreis":"LK Schaumburg" }, 35 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3351", "Landkreis":"LK Celle" }, 36 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3352", "Landkreis":"LK Cuxhaven" }, 37 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3353", "Landkreis":"LK Harburg" }, 38 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3354", "Landkreis":"LK Lüchow-Dannenberg" }, 39 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3355", "Landkreis":"LK Lüneburg" }, 40 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3356", "Landkreis":"LK Osterholz" }, 41 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3357", "Landkreis":"LK Rotenburg (Wümme)" }, 42 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3358", "Landkreis":"LK Heidekreis" }, 43 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3359", "Landkreis":"LK Stade" }, 44 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3360", "Landkreis":"LK Uelzen" }, 45 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3361", "Landkreis":"LK Verden" }, 46 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3401", "Landkreis":"SK Delmenhorst" }, 47 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3402", "Landkreis":"SK Emden" }, 48 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3403", "Landkreis":"SK Oldenburg" }, 49 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3404", "Landkreis":"SK Osnabrück" }, 50 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3405", "Landkreis":"SK Wilhelmshaven" }, 51 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3451", "Landkreis":"LK Ammerland" }, 52 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3452", "Landkreis":"LK Aurich" }, 53 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3453", "Landkreis":"LK Cloppenburg" }, 54 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3454", "Landkreis":"LK Emsland" }, 55 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3455", "Landkreis":"LK Friesland" }, 56 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3456", "Landkreis":"LK Grafschaft Bentheim" }, 57 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3457", "Landkreis":"LK Leer" }, 58 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3458", "Landkreis":"LK Oldenburg" }, 59 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3459", "Landkreis":"LK Osnabrück" }, 60 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3460", "Landkreis":"LK Vechta" }, 61 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3461", "Landkreis":"LK Wesermarsch" }, 62 | { "IdBundesland":3, "Bundesland":"Niedersachsen", "IdLandkreis":"3462", "Landkreis":"LK Wittmund" }, 63 | { "IdBundesland":4, "Bundesland":"Bremen", "IdLandkreis":"4011", "Landkreis":"SK Bremen" }, 64 | { "IdBundesland":4, "Bundesland":"Bremen", "IdLandkreis":"4012", "Landkreis":"SK Bremerhaven" }, 65 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5111", "Landkreis":"SK Düsseldorf" }, 66 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5112", "Landkreis":"SK Duisburg" }, 67 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5113", "Landkreis":"SK Essen" }, 68 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5114", "Landkreis":"SK Krefeld" }, 69 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5116", "Landkreis":"SK Mönchengladbach" }, 70 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5117", "Landkreis":"SK Mülheim a.d.Ruhr" }, 71 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5119", "Landkreis":"SK Oberhausen" }, 72 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5120", "Landkreis":"SK Remscheid" }, 73 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5122", "Landkreis":"SK Solingen" }, 74 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5124", "Landkreis":"SK Wuppertal" }, 75 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5154", "Landkreis":"LK Kleve" }, 76 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5158", "Landkreis":"LK Mettmann" }, 77 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5162", "Landkreis":"LK Rhein-Kreis Neuss" }, 78 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5166", "Landkreis":"LK Viersen" }, 79 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5170", "Landkreis":"LK Wesel" }, 80 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5314", "Landkreis":"SK Bonn" }, 81 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5315", "Landkreis":"SK Köln" }, 82 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5316", "Landkreis":"SK Leverkusen" }, 83 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5334", "Landkreis":"StädteRegion Aachen" }, 84 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5358", "Landkreis":"LK Düren" }, 85 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5362", "Landkreis":"LK Rhein-Erft-Kreis" }, 86 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5366", "Landkreis":"LK Euskirchen" }, 87 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5370", "Landkreis":"LK Heinsberg" }, 88 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5374", "Landkreis":"LK Oberbergischer Kreis" }, 89 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5378", "Landkreis":"LK Rheinisch-Bergischer Kreis" }, 90 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5382", "Landkreis":"LK Rhein-Sieg-Kreis" }, 91 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5512", "Landkreis":"SK Bottrop" }, 92 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5513", "Landkreis":"SK Gelsenkirchen" }, 93 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5515", "Landkreis":"SK Münster" }, 94 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5554", "Landkreis":"LK Borken" }, 95 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5558", "Landkreis":"LK Coesfeld" }, 96 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5562", "Landkreis":"LK Recklinghausen" }, 97 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5566", "Landkreis":"LK Steinfurt" }, 98 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5570", "Landkreis":"LK Warendorf" }, 99 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5711", "Landkreis":"SK Bielefeld" }, 100 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5754", "Landkreis":"LK Gütersloh" }, 101 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5758", "Landkreis":"LK Herford" }, 102 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5762", "Landkreis":"LK Höxter" }, 103 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5766", "Landkreis":"LK Lippe" }, 104 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5770", "Landkreis":"LK Minden-Lübbecke" }, 105 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5774", "Landkreis":"LK Paderborn" }, 106 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5911", "Landkreis":"SK Bochum" }, 107 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5913", "Landkreis":"SK Dortmund" }, 108 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5914", "Landkreis":"SK Hagen" }, 109 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5915", "Landkreis":"SK Hamm" }, 110 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5916", "Landkreis":"SK Herne" }, 111 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5954", "Landkreis":"LK Ennepe-Ruhr-Kreis" }, 112 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5958", "Landkreis":"LK Hochsauerlandkreis" }, 113 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5962", "Landkreis":"LK Märkischer Kreis" }, 114 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5966", "Landkreis":"LK Olpe" }, 115 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5970", "Landkreis":"LK Siegen-Wittgenstein" }, 116 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5974", "Landkreis":"LK Soest" }, 117 | { "IdBundesland":5, "Bundesland":"Nordrhein-Westfalen", "IdLandkreis":"5978", "Landkreis":"LK Unna" }, 118 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6411", "Landkreis":"SK Darmstadt" }, 119 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6412", "Landkreis":"SK Frankfurt am Main" }, 120 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6413", "Landkreis":"SK Offenbach" }, 121 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6414", "Landkreis":"SK Wiesbaden" }, 122 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6431", "Landkreis":"LK Bergstraße" }, 123 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6432", "Landkreis":"LK Darmstadt-Dieburg" }, 124 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6433", "Landkreis":"LK Groß-Gerau" }, 125 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6434", "Landkreis":"LK Hochtaunuskreis" }, 126 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6435", "Landkreis":"LK Main-Kinzig-Kreis" }, 127 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6436", "Landkreis":"LK Main-Taunus-Kreis" }, 128 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6437", "Landkreis":"LK Odenwaldkreis" }, 129 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6438", "Landkreis":"LK Offenbach" }, 130 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6439", "Landkreis":"LK Rheingau-Taunus-Kreis" }, 131 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6440", "Landkreis":"LK Wetteraukreis" }, 132 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6531", "Landkreis":"LK Gießen" }, 133 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6532", "Landkreis":"LK Lahn-Dill-Kreis" }, 134 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6533", "Landkreis":"LK Limburg-Weilburg" }, 135 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6534", "Landkreis":"LK Marburg-Biedenkopf" }, 136 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6535", "Landkreis":"LK Vogelsbergkreis" }, 137 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6611", "Landkreis":"SK Kassel" }, 138 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6631", "Landkreis":"LK Fulda" }, 139 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6632", "Landkreis":"LK Hersfeld-Rotenburg" }, 140 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6633", "Landkreis":"LK Kassel" }, 141 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6634", "Landkreis":"LK Schwalm-Eder-Kreis" }, 142 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6635", "Landkreis":"LK Waldeck-Frankenberg" }, 143 | { "IdBundesland":6, "Bundesland":"Hessen", "IdLandkreis":"6636", "Landkreis":"LK Werra-Meißner-Kreis" }, 144 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7111", "Landkreis":"SK Koblenz" }, 145 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7131", "Landkreis":"LK Ahrweiler" }, 146 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7132", "Landkreis":"LK Altenkirchen" }, 147 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7133", "Landkreis":"LK Bad Kreuznach" }, 148 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7134", "Landkreis":"LK Birkenfeld" }, 149 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7135", "Landkreis":"LK Cochem-Zell" }, 150 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7137", "Landkreis":"LK Mayen-Koblenz" }, 151 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7138", "Landkreis":"LK Neuwied" }, 152 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7140", "Landkreis":"LK Rhein-Hunsrück-Kreis" }, 153 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7141", "Landkreis":"LK Rhein-Lahn-Kreis" }, 154 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7143", "Landkreis":"LK Westerwaldkreis" }, 155 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7211", "Landkreis":"SK Trier" }, 156 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7231", "Landkreis":"LK Bernkastel-Wittlich" }, 157 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7232", "Landkreis":"LK Bitburg-Prüm" }, 158 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7233", "Landkreis":"LK Vulkaneifel" }, 159 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7235", "Landkreis":"LK Trier-Saarburg" }, 160 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7311", "Landkreis":"SK Frankenthal" }, 161 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7312", "Landkreis":"SK Kaiserslautern" }, 162 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7313", "Landkreis":"SK Landau i.d.Pfalz" }, 163 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7314", "Landkreis":"SK Ludwigshafen" }, 164 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7315", "Landkreis":"SK Mainz" }, 165 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7316", "Landkreis":"SK Neustadt a.d.Weinstraße" }, 166 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7317", "Landkreis":"SK Pirmasens" }, 167 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7318", "Landkreis":"SK Speyer" }, 168 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7319", "Landkreis":"SK Worms" }, 169 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7320", "Landkreis":"SK Zweibrücken" }, 170 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7331", "Landkreis":"LK Alzey-Worms" }, 171 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7332", "Landkreis":"LK Bad Dürkheim" }, 172 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7333", "Landkreis":"LK Donnersbergkreis" }, 173 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7334", "Landkreis":"LK Germersheim" }, 174 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7335", "Landkreis":"LK Kaiserslautern" }, 175 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7336", "Landkreis":"LK Kusel" }, 176 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7337", "Landkreis":"LK Südliche Weinstraße" }, 177 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7338", "Landkreis":"LK Rhein-Pfalz-Kreis" }, 178 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7339", "Landkreis":"LK Mainz-Bingen" }, 179 | { "IdBundesland":7, "Bundesland":"Rheinland-Pfalz", "IdLandkreis":"7340", "Landkreis":"LK Südwestpfalz" }, 180 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8111", "Landkreis":"SK Stuttgart" }, 181 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8115", "Landkreis":"LK Böblingen" }, 182 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8116", "Landkreis":"LK Esslingen" }, 183 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8117", "Landkreis":"LK Göppingen" }, 184 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8118", "Landkreis":"LK Ludwigsburg" }, 185 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8119", "Landkreis":"LK Rems-Murr-Kreis" }, 186 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8121", "Landkreis":"SK Heilbronn" }, 187 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8125", "Landkreis":"LK Heilbronn" }, 188 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8126", "Landkreis":"LK Hohenlohekreis" }, 189 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8127", "Landkreis":"LK Schwäbisch Hall" }, 190 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8128", "Landkreis":"LK Main-Tauber-Kreis" }, 191 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8135", "Landkreis":"LK Heidenheim" }, 192 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8136", "Landkreis":"LK Ostalbkreis" }, 193 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8211", "Landkreis":"SK Baden-Baden" }, 194 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8212", "Landkreis":"SK Karlsruhe" }, 195 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8215", "Landkreis":"LK Karlsruhe" }, 196 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8216", "Landkreis":"LK Rastatt" }, 197 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8221", "Landkreis":"SK Heidelberg" }, 198 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8222", "Landkreis":"SK Mannheim" }, 199 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8225", "Landkreis":"LK Neckar-Odenwald-Kreis" }, 200 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8226", "Landkreis":"LK Rhein-Neckar-Kreis" }, 201 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8231", "Landkreis":"SK Pforzheim" }, 202 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8235", "Landkreis":"LK Calw" }, 203 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8236", "Landkreis":"LK Enzkreis" }, 204 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8237", "Landkreis":"LK Freudenstadt" }, 205 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8311", "Landkreis":"SK Freiburg i.Breisgau" }, 206 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8315", "Landkreis":"LK Breisgau-Hochschwarzwald" }, 207 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8316", "Landkreis":"LK Emmendingen" }, 208 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8317", "Landkreis":"LK Ortenaukreis" }, 209 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8325", "Landkreis":"LK Rottweil" }, 210 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8326", "Landkreis":"LK Schwarzwald-Baar-Kreis" }, 211 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8327", "Landkreis":"LK Tuttlingen" }, 212 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8335", "Landkreis":"LK Konstanz" }, 213 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8336", "Landkreis":"LK Lörrach" }, 214 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8337", "Landkreis":"LK Waldshut" }, 215 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8415", "Landkreis":"LK Reutlingen" }, 216 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8416", "Landkreis":"LK Tübingen" }, 217 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8417", "Landkreis":"LK Zollernalbkreis" }, 218 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8421", "Landkreis":"SK Ulm" }, 219 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8425", "Landkreis":"LK Alb-Donau-Kreis" }, 220 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8426", "Landkreis":"LK Biberach" }, 221 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8435", "Landkreis":"LK Bodenseekreis" }, 222 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8436", "Landkreis":"LK Ravensburg" }, 223 | { "IdBundesland":8, "Bundesland":"Baden-Württemberg", "IdLandkreis":"8437", "Landkreis":"LK Sigmaringen" }, 224 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9161", "Landkreis":"SK Ingolstadt" }, 225 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9162", "Landkreis":"SK München" }, 226 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9163", "Landkreis":"SK Rosenheim" }, 227 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9171", "Landkreis":"LK Altötting" }, 228 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9172", "Landkreis":"LK Berchtesgadener Land" }, 229 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9173", "Landkreis":"LK Bad Tölz-Wolfratshausen" }, 230 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9174", "Landkreis":"LK Dachau" }, 231 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9175", "Landkreis":"LK Ebersberg" }, 232 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9176", "Landkreis":"LK Eichstätt" }, 233 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9177", "Landkreis":"LK Erding" }, 234 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9178", "Landkreis":"LK Freising" }, 235 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9179", "Landkreis":"LK Fürstenfeldbruck" }, 236 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9180", "Landkreis":"LK Garmisch-Partenkirchen" }, 237 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9181", "Landkreis":"LK Landsberg a.Lech" }, 238 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9182", "Landkreis":"LK Miesbach" }, 239 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9183", "Landkreis":"LK Mühldorf a.Inn" }, 240 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9184", "Landkreis":"LK München" }, 241 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9185", "Landkreis":"LK Neuburg-Schrobenhausen" }, 242 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9186", "Landkreis":"LK Pfaffenhofen a.d.Ilm" }, 243 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9187", "Landkreis":"LK Rosenheim" }, 244 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9188", "Landkreis":"LK Starnberg" }, 245 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9189", "Landkreis":"LK Traunstein" }, 246 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9190", "Landkreis":"LK Weilheim-Schongau" }, 247 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9261", "Landkreis":"SK Landshut" }, 248 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9262", "Landkreis":"SK Passau" }, 249 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9263", "Landkreis":"SK Straubing" }, 250 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9271", "Landkreis":"LK Deggendorf" }, 251 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9272", "Landkreis":"LK Freyung-Grafenau" }, 252 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9273", "Landkreis":"LK Kelheim" }, 253 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9274", "Landkreis":"LK Landshut" }, 254 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9275", "Landkreis":"LK Passau" }, 255 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9276", "Landkreis":"LK Regen" }, 256 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9277", "Landkreis":"LK Rottal-Inn" }, 257 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9278", "Landkreis":"LK Straubing-Bogen" }, 258 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9279", "Landkreis":"LK Dingolfing-Landau" }, 259 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9361", "Landkreis":"SK Amberg" }, 260 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9362", "Landkreis":"SK Regensburg" }, 261 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9363", "Landkreis":"SK Weiden i.d.OPf." }, 262 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9371", "Landkreis":"LK Amberg-Sulzbach" }, 263 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9372", "Landkreis":"LK Cham" }, 264 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9373", "Landkreis":"LK Neumarkt i.d.OPf." }, 265 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9374", "Landkreis":"LK Neustadt a.d.Waldnaab" }, 266 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9375", "Landkreis":"LK Regensburg" }, 267 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9376", "Landkreis":"LK Schwandorf" }, 268 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9377", "Landkreis":"LK Tirschenreuth" }, 269 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9461", "Landkreis":"SK Bamberg" }, 270 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9462", "Landkreis":"SK Bayreuth" }, 271 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9463", "Landkreis":"SK Coburg" }, 272 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9464", "Landkreis":"SK Hof" }, 273 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9471", "Landkreis":"LK Bamberg" }, 274 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9472", "Landkreis":"LK Bayreuth" }, 275 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9473", "Landkreis":"LK Coburg" }, 276 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9474", "Landkreis":"LK Forchheim" }, 277 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9475", "Landkreis":"LK Hof" }, 278 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9476", "Landkreis":"LK Kronach" }, 279 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9477", "Landkreis":"LK Kulmbach" }, 280 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9478", "Landkreis":"LK Lichtenfels" }, 281 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9479", "Landkreis":"LK Wunsiedel i.Fichtelgebirge" }, 282 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9561", "Landkreis":"SK Ansbach" }, 283 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9562", "Landkreis":"SK Erlangen" }, 284 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9563", "Landkreis":"SK Fürth" }, 285 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9564", "Landkreis":"SK Nürnberg" }, 286 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9565", "Landkreis":"SK Schwabach" }, 287 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9571", "Landkreis":"LK Ansbach" }, 288 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9572", "Landkreis":"LK Erlangen-Höchstadt" }, 289 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9573", "Landkreis":"LK Fürth" }, 290 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9574", "Landkreis":"LK Nürnberger Land" }, 291 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9575", "Landkreis":"LK Neustadt a.d.Aisch-Bad Windsheim" }, 292 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9576", "Landkreis":"LK Roth" }, 293 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9577", "Landkreis":"LK Weißenburg-Gunzenhausen" }, 294 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9661", "Landkreis":"SK Aschaffenburg" }, 295 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9662", "Landkreis":"SK Schweinfurt" }, 296 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9663", "Landkreis":"SK Würzburg" }, 297 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9671", "Landkreis":"LK Aschaffenburg" }, 298 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9672", "Landkreis":"LK Bad Kissingen" }, 299 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9673", "Landkreis":"LK Rhön-Grabfeld" }, 300 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9674", "Landkreis":"LK Haßberge" }, 301 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9675", "Landkreis":"LK Kitzingen" }, 302 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9676", "Landkreis":"LK Miltenberg" }, 303 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9677", "Landkreis":"LK Main-Spessart" }, 304 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9678", "Landkreis":"LK Schweinfurt" }, 305 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9679", "Landkreis":"LK Würzburg" }, 306 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9761", "Landkreis":"SK Augsburg" }, 307 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9762", "Landkreis":"SK Kaufbeuren" }, 308 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9763", "Landkreis":"SK Kempten" }, 309 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9764", "Landkreis":"SK Memmingen" }, 310 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9771", "Landkreis":"LK Aichach-Friedberg" }, 311 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9772", "Landkreis":"LK Augsburg" }, 312 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9773", "Landkreis":"LK Dillingen a.d.Donau" }, 313 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9774", "Landkreis":"LK Günzburg" }, 314 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9775", "Landkreis":"LK Neu-Ulm" }, 315 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9776", "Landkreis":"LK Lindau" }, 316 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9777", "Landkreis":"LK Ostallgäu" }, 317 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9778", "Landkreis":"LK Unterallgäu" }, 318 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9779", "Landkreis":"LK Donau-Ries" }, 319 | { "IdBundesland":9, "Bundesland":"Bayern", "IdLandkreis":"9780", "Landkreis":"LK Oberallgäu" }, 320 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10041", "Landkreis":"LK Stadtverband Saarbrücken" }, 321 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10042", "Landkreis":"LK Merzig-Wadern" }, 322 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10043", "Landkreis":"LK Neunkirchen" }, 323 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10044", "Landkreis":"LK Saarlouis" }, 324 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10045", "Landkreis":"LK Saarpfalz-Kreis" }, 325 | { "IdBundesland":10, "Bundesland":"Saarland", "IdLandkreis":"10046", "Landkreis":"LK Sankt Wendel" }, 326 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11001", "Landkreis":"SK Berlin Mitte" }, 327 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11002", "Landkreis":"SK Berlin Friedrichshain-Kreuzberg" }, 328 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11003", "Landkreis":"SK Berlin Pankow" }, 329 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11004", "Landkreis":"SK Berlin Charlottenburg-Wilmersdorf" }, 330 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11005", "Landkreis":"SK Berlin Spandau" }, 331 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11006", "Landkreis":"SK Berlin Steglitz-Zehlendorf" }, 332 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11007", "Landkreis":"SK Berlin Tempelhof-Schöneberg" }, 333 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11008", "Landkreis":"SK Berlin Neukölln" }, 334 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11009", "Landkreis":"SK Berlin Treptow-Köpenick" }, 335 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11010", "Landkreis":"SK Berlin Marzahn-Hellersdorf" }, 336 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11011", "Landkreis":"SK Berlin Lichtenberg" }, 337 | { "IdBundesland":11, "Bundesland":"Berlin", "IdLandkreis":"11012", "Landkreis":"SK Berlin Reinickendorf" }, 338 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12051", "Landkreis":"SK Brandenburg a.d.Havel" }, 339 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12052", "Landkreis":"SK Cottbus" }, 340 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12053", "Landkreis":"SK Frankfurt (Oder)" }, 341 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12054", "Landkreis":"SK Potsdam" }, 342 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12060", "Landkreis":"LK Barnim" }, 343 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12061", "Landkreis":"LK Dahme-Spreewald" }, 344 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12062", "Landkreis":"LK Elbe-Elster" }, 345 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12063", "Landkreis":"LK Havelland" }, 346 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12064", "Landkreis":"LK Märkisch-Oderland" }, 347 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12065", "Landkreis":"LK Oberhavel" }, 348 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12066", "Landkreis":"LK Oberspreewald-Lausitz" }, 349 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12067", "Landkreis":"LK Oder-Spree" }, 350 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12068", "Landkreis":"LK Ostprignitz-Ruppin" }, 351 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12069", "Landkreis":"LK Potsdam-Mittelmark" }, 352 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12070", "Landkreis":"LK Prignitz" }, 353 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12071", "Landkreis":"LK Spree-Neiße" }, 354 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12072", "Landkreis":"LK Teltow-Fläming" }, 355 | { "IdBundesland":12, "Bundesland":"Brandenburg", "IdLandkreis":"12073", "Landkreis":"LK Uckermark" }, 356 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13003", "Landkreis":"SK Rostock" }, 357 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13004", "Landkreis":"SK Schwerin" }, 358 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13071", "Landkreis":"LK Mecklenburgische Seenplatte" }, 359 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13072", "Landkreis":"LK Rostock" }, 360 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13073", "Landkreis":"LK Vorpommern-Rügen" }, 361 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13074", "Landkreis":"LK Nordwestmecklenburg" }, 362 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13075", "Landkreis":"LK Vorpommern-Greifswald" }, 363 | { "IdBundesland":13, "Bundesland":"Mecklenburg-Vorpommern", "IdLandkreis":"13076", "Landkreis":"LK Ludwigslust-Parchim" }, 364 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14511", "Landkreis":"SK Chemnitz" }, 365 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14521", "Landkreis":"LK Erzgebirgskreis" }, 366 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14522", "Landkreis":"LK Mittelsachsen" }, 367 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14523", "Landkreis":"LK Vogtlandkreis" }, 368 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14524", "Landkreis":"LK Zwickau" }, 369 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14612", "Landkreis":"SK Dresden" }, 370 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14625", "Landkreis":"LK Bautzen" }, 371 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14626", "Landkreis":"LK Görlitz" }, 372 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14627", "Landkreis":"LK Meißen" }, 373 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14628", "Landkreis":"LK Sächsische Schweiz-Osterzgebirge" }, 374 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14713", "Landkreis":"SK Leipzig" }, 375 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14729", "Landkreis":"LK Leipzig" }, 376 | { "IdBundesland":14, "Bundesland":"Sachsen", "IdLandkreis":"14730", "Landkreis":"LK Nordsachsen" }, 377 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15001", "Landkreis":"SK Dessau-Roßlau" }, 378 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15002", "Landkreis":"SK Halle" }, 379 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15003", "Landkreis":"SK Magdeburg" }, 380 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15081", "Landkreis":"LK Altmarkkreis Salzwedel" }, 381 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15082", "Landkreis":"LK Anhalt-Bitterfeld" }, 382 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15083", "Landkreis":"LK Börde" }, 383 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15084", "Landkreis":"LK Burgenlandkreis" }, 384 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15085", "Landkreis":"LK Harz" }, 385 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15086", "Landkreis":"LK Jerichower Land" }, 386 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15087", "Landkreis":"LK Mansfeld-Südharz" }, 387 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15088", "Landkreis":"LK Saalekreis" }, 388 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15089", "Landkreis":"LK Salzlandkreis" }, 389 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15090", "Landkreis":"LK Stendal" }, 390 | { "IdBundesland":15, "Bundesland":"Sachsen-Anhalt", "IdLandkreis":"15091", "Landkreis":"LK Wittenberg" }, 391 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16051", "Landkreis":"SK Erfurt" }, 392 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16052", "Landkreis":"SK Gera" }, 393 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16053", "Landkreis":"SK Jena" }, 394 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16054", "Landkreis":"SK Suhl" }, 395 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16055", "Landkreis":"SK Weimar" }, 396 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16061", "Landkreis":"LK Eichsfeld" }, 397 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16062", "Landkreis":"LK Nordhausen" }, 398 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16063", "Landkreis":"LK Wartburgkreis" }, 399 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16064", "Landkreis":"LK Unstrut-Hainich-Kreis" }, 400 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16065", "Landkreis":"LK Kyffhäuserkreis" }, 401 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16066", "Landkreis":"LK Schmalkalden-Meiningen" }, 402 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16067", "Landkreis":"LK Gotha" }, 403 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16068", "Landkreis":"LK Sömmerda" }, 404 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16069", "Landkreis":"LK Hildburghausen" }, 405 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16070", "Landkreis":"LK Ilm-Kreis" }, 406 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16071", "Landkreis":"LK Weimarer Land" }, 407 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16072", "Landkreis":"LK Sonneberg" }, 408 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16073", "Landkreis":"LK Saalfeld-Rudolstadt" }, 409 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16074", "Landkreis":"LK Saale-Holzland-Kreis" }, 410 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16075", "Landkreis":"LK Saale-Orla-Kreis" }, 411 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16076", "Landkreis":"LK Greiz" }, 412 | { "IdBundesland":16, "Bundesland":"Thüringen", "IdLandkreis":"16077", "Landkreis":"LK Altenburger Land" } 413 | ] -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2020-rki-archive", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "2020-rki-archive", 9 | "version": "1.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "colors": "^1.4.0" 13 | } 14 | }, 15 | "node_modules/colors": { 16 | "version": "1.4.0", 17 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 18 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 19 | "engines": { 20 | "node": ">=0.1.90" 21 | } 22 | } 23 | }, 24 | "dependencies": { 25 | "colors": { 26 | "version": "1.4.0", 27 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 28 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "2020-rki-archive", 3 | "version": "1.0.0", 4 | "description": "RKI corona data archive", 5 | "author": "Michael Kreil (BR)", 6 | "license": "MIT", 7 | "dependencies": { 8 | "colors": "^1.4.0" 9 | } 10 | } 11 | --------------------------------------------------------------------------------