Skip to content

Instantly share code, notes, and snippets.

@martinharder
Last active October 10, 2022 12:52
Show Gist options
  • Save martinharder/333300075dde7b31a28f1a5243d8f5b9 to your computer and use it in GitHub Desktop.
Save martinharder/333300075dde7b31a28f1a5243d8f5b9 to your computer and use it in GitHub Desktop.
COVID-19 Intensivbettenbelegung. Ein Widget für Scriptable
const newCasesApiUrl = `https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/DIVI_Intensivregister_Landkreise/FeatureServer/0/query?f=json&where=1%3D1&returnGeometry=false&spatialRel=esriSpatialRelIntersects&outFields=*&orderByFields=Anteil_betten_frei%20desc&resultOffset=0&resultRecordCount=4000&resultType=standard&cacheHint=true`;
/* Bundesland-ID:
Baden-Württemberg: 8
Bayern: 9
Berlin: 11
Brandenburg: 12
Bremen: 4
Hamburg: 2
Hessen: 6
Mecklenburg-Vorpommern: 13
Niedersachsen: 3
Nordrhein-Westfalen: 5
Rheinland-Pfalz: 7
Saarland: 10
Sachsen: 14
Sachsen-Anhalt: 15
Schleswig-Holstein: 1
Thüringen: 16
*/
const blTitle = {
1: 'SH',
2: 'HAMBURG',
3: 'NI',
4: 'BREMEN',
5: 'NRW',
6: 'HE',
7: 'RP',
8: 'BW',
9: 'BAYERN',
10: 'SL',
11: 'BERLIN',
12: 'BB',
13: 'MV',
14: 'SN',
15: 'ST',
16: 'TH'
}
const params = args.widgetParameter ? args.widgetParameter.split(',') : null;
const areaParam = params && params.length > 0 ? params[0].trim() : null;
const name = params && params.length === 2 ? params[1].trim() : null;
let bl = areaParam && +areaParam > 0 && +areaParam < 17 ? areaParam.toString() : null
bl = (bl && bl.length === 2 && bl.substr(0, 1) === '0') ? bl.substr(1,1) : bl
let lk = areaParam && +areaParam >= 01001 && +areaParam <= 16077 ? areaParam.toString() : null
lk = (lk && lk.length === 4) ? '0' + lk : lk
function calculateTotals(data) {
let betten_frei = 0
let betten_belegt = 0
let betten_gesamt = 0
let faelle_covid_aktuell = 0
let faelle_covid_aktuell_beatmet = 0
let blDataCount = 0
let county = null
if (lk) {
for (let i = 0; i < data.features.length; i++) {
const feature = data.features[i]
if (feature.attributes.AGS === lk) {
betten_gesamt = feature.attributes.betten_gesamt
betten_belegt = feature.attributes.betten_belegt
betten_frei = feature.attributes.betten_frei
faelle_covid_aktuell = feature.attributes.faelle_covid_aktuell
faelle_covid_aktuell_beatmet = feature.attributes.faelle_covid_aktuell_beatmet
county = feature.attributes.county
break;
}
}
} else {
data.features.forEach(feature => {
betten_gesamt += !bl || (bl && feature.attributes.BL_ID === bl) ? feature.attributes.betten_gesamt : 0
betten_belegt += !bl || (bl && feature.attributes.BL_ID === bl) ? feature.attributes.betten_belegt : 0
betten_frei += !bl || (bl && feature.attributes.BL_ID === bl) ? feature.attributes.betten_frei : 0
faelle_covid_aktuell += !bl || (bl && feature.attributes.BL_ID === bl) ? feature.attributes.faelle_covid_aktuell : 0
faelle_covid_aktuell_beatmet += !bl || (bl && feature.attributes.BL_ID === bl) ? feature.attributes.faelle_covid_aktuell_beatmet : 0
if (bl && feature.attributes.BL_ID === bl) {
blDataCount++
}
})
}
return {
betten_gesamt,
betten_belegt,
betten_frei,
faelle_covid_aktuell,
faelle_covid_aktuell_beatmet,
anteil_covid_betten: faelle_covid_aktuell > 0 && betten_belegt > 0 ? faelle_covid_aktuell * 100 / betten_belegt : 0,
anteil_beatmet: faelle_covid_aktuell_beatmet > 0 && faelle_covid_aktuell > 0 ? faelle_covid_aktuell_beatmet * 100 / faelle_covid_aktuell : 0,
freie_betten: betten_frei > 0 && betten_gesamt > 0 ? betten_frei * 100 / betten_gesamt : 0,
stand: data.features[0].attributes.daten_stand,
blDataCount,
county
}
}
let widget = await createWidget()
if (!config.runsInWidget) {
await widget.presentSmall()
}
Script.setWidget(widget)
Script.complete()
async function createWidget(items) {
let data, header, label
const widget = new ListWidget()
// fetch data
data = await new Request(newCasesApiUrl).loadJSON()
if (!data || !data.features || !data.features.length) {
const errorList = new ListWidget()
errorList.addText("Daten konnten nicht abgerufen werden.")
return errorList
}
const totals = calculateTotals(data)
if (bl && totals.blDataCount === 0) {
const errorList = new ListWidget()
errorList.addText(`Keine Daten für BL ${bl}`)
return errorList
}
if (lk && !totals.county) {
const errorList = new ListWidget()
errorList.addText(`Keine Daten für Landkreis ${lk}`)
return errorList
}
const headerTitle = name ? name : bl ? 'BL ' + blTitle[parseInt(args.widgetParameter)] : lk && totals.county ? totals.county : 'Intensivbetten'
header = widget.addText("🏥 " + headerTitle.toUpperCase())
header.centerAlignText()
header.font = Font.mediumSystemFont(10)
widget.addSpacer()
const infoText1 = widget.addText("COVID-19 Patienten".toUpperCase())
infoText1.centerAlignText()
infoText1.font = Font.mediumSystemFont(9)
label = widget.addText(totals.faelle_covid_aktuell.toLocaleString())
label.font = Font.mediumSystemFont(15)
label.centerAlignText()
const infoText2 = widget.addText(totals.anteil_covid_betten.toFixed(2) + "% der Betten")
infoText2.centerAlignText()
infoText2.font = Font.mediumSystemFont(9)
infoText2.textColor = Color.gray()
widget.addSpacer()
header = widget.addText("Davon beatmet".toUpperCase())
header.centerAlignText()
header.font = Font.mediumSystemFont(9)
label = widget.addText(totals.faelle_covid_aktuell_beatmet.toLocaleString())
label.centerAlignText()
label.font = Font.mediumSystemFont(15)
const infoText3 = widget.addText(totals.anteil_beatmet.toFixed(2) + "%")
infoText3.centerAlignText()
infoText3.font = Font.mediumSystemFont(9)
infoText3.textColor = Color.gray()
widget.addSpacer()
const infoText4 = widget.addText(totals.freie_betten.toFixed(2) + "% Betten frei")
infoText4.centerAlignText()
infoText4.font = Font.mediumSystemFont(10)
infoText4.textColor = totals.freie_betten > 25 ? Color.green() : totals.freie_betten > 10 ? Color.yellow() : Color.red()
const infoText5 = widget.addText(totals.betten_frei.toLocaleString() + ' von ' + totals.betten_gesamt.toLocaleString())
infoText5.centerAlignText()
infoText5.font = Font.mediumSystemFont(9)
infoText5.textColor = totals.freie_betten > 25 ? Color.green() : totals.freie_betten > 10 ? Color.yellow() : Color.red()
label = widget.addText("Stand: " + totals.stand.substr(0, 10))
label.centerAlignText()
label.font = Font.mediumSystemFont(8)
label.textColor = Color.gray()
return widget
}
@dennerforen
Copy link

@martinharder

Als Parameter wäre mir lieber, noch kleinere Schrift ist auf se 1 eher nicht...

@martinharder
Copy link
Author

Hab es kurzfristig eingebaut. Nach der BL-ID oder LK-ID kann durch ein Komma getrennt ein Name angegeben werden.

@dennerforen
Copy link

Super, vielen Dank, funktioniert 👍😀

@dennerforen
Copy link

Hi Martin, Es stehen seit ein paar Tagen nur noch die Daten vom Vortag im Widget, nicht mehr Stunden aktuell.

@martinharder
Copy link
Author

Ich habe mir das Ergebnis angeschaut, was wir von der Schnittstelle bekommen. Da ist der Stand leider auch vom Vortag angegeben. Ich weiß leider nicht, woran das liegt, versuche es aber herauszufinden.

@dennerforen
Copy link

Danke. Dieses Widget bekommt die aktuellen Daten, vielleicht findest du ja da einen Hinweis.

https://gist.github.com/Keyes/7c357ae694d3762fcfbe3869c9e966ea

@lululasse
Copy link

Hi Martin, eigentlich müssten die Daten jetzt zumindest den Stand vom 16.12. anzeigen, oder? ich habe immer noch 15.12. Weißt Du was das Problem ist?

@martinharder
Copy link
Author

@dennerforen ich habe dort nach der Quelle nachgefragt, mal sehen. Aber seit heute scheinen die Daten wieder aktuell zu sein.
Hast du die Zahlen verglichen? Waren sie tatsächlich veraltet oder war der Zeitstempel nur falsch?

@lululasse da war es noch nicht Mittag ;) Sie aktualisieren die Daten immer erst gegen Mittag, manchmal auch später.

@dennerforen
Copy link

Ja, seltsam. Nein, die Zahlen hatte ich nicht verglichen, da habe ich mich vom Datum begleiten lassen.

Heute kommt es so einigermaßen hin, sind nur kleine Abweichungen. Wohl abhängig vom Aktualisierungszeitpunkt.
IMG_0887

@ChrisRo1987
Copy link

Vielen Dank für die tolle Arbeit!
Wäre es möglich ein Script zu erstellen welches die Auslastung in Zahlen zeigt, damit wüsste man schnell ab wann die Ampel Regeln aus der PK von 03.11.2021 in Bayern gelten!

Vielen Dank

@martinharder
Copy link
Author

Hallo ChrisRo1987, was genau meinst du mit Auslastung in Zahlen? Das sollte die letzte farbige Zeile in dem Widget darstellen).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment