Forked from dwd0tcom/incidence-vaccines-scriptable.js
Last active
May 14, 2021 07:06
-
-
Save caspahouzer/2b529b616d88bc64f1124f79d8a5bd32 to your computer and use it in GitHub Desktop.
A scriptable widget to display and show the current incidence and vaccine status.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Variables used by Scriptable. | |
// These must be at the very top of the file. Do not edit. | |
// icon-color: deep-gray; icon-glyph: magic; | |
// Licence: Robert Koch-Institut (RKI), dl-de/by-2-0 | |
// Vaccine API by @_ThisIsBenny_ | |
// Define URLs based on the corona.rki.de webpage | |
const newCasesApiUrl = `https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_COVID19/FeatureServer/0/query?f=json&where=NeuerFall%20IN(1%2C%20-1)&returnGeometry=false&spatialRel=esriSpatialRelIntersects&outFields=*&outStatistics=%5B%7B%22statisticType%22%3A%22sum%22%2C%22onStatisticField%22%3A%22AnzahlFall%22%2C%22outStatisticFieldName%22%3A%22value%22%7D%5D&resultType=standard&cacheHint=true`; | |
const incidenceUrl = (location) => | |
`https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=1%3D1&outFields=GEN,cases7_per_100k&geometry=${location.longitude.toFixed( | |
3 | |
)}%2C${location.latitude.toFixed( | |
3 | |
)}&geometryType=esriGeometryPoint&inSR=4326&spatialRel=esriSpatialRelWithin&returnGeometry=false&outSR=4326&f=json`; | |
const incidenceUrlStates = | |
"https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/Coronaf%E4lle_in_den_Bundesl%E4ndern/FeatureServer/0/query?where=1%3D1&outFields=cases7_bl_per_100k&returnGeometry=false&outSR=4326&f=json"; | |
const vaccineStatus = "https://rki-vaccination-data.vercel.app/api"; | |
// Initialize Widget | |
let widget = await createWidget(); | |
if (!config.runsInWidget) { | |
await widget.presentSmall(); | |
} | |
Script.setWidget(widget); | |
Script.complete(); | |
// Build Widget | |
async function createWidget(items) { | |
const list = new ListWidget(); | |
let header, label, localIncedence, germanIncedence; | |
// fetch new cases | |
const newCasesData = await getNewCasesData(); | |
header = list.addText("🦠 Neuinfektionen".toUpperCase()); | |
header.font = Font.mediumSystemFont(10); | |
label = list.addText("+" + newCasesData.value.toLocaleString()); | |
label.font = Font.mediumSystemFont(24); | |
const country = list.addText(newCasesData.areaName); | |
country.font = Font.mediumSystemFont(12); | |
country.textColor = Color.gray(); | |
list.addSpacer(); | |
// fetch new incidents | |
const incidenceData = await getIncidenceData(); | |
header = list.addText("🦠 Inzidenz".toUpperCase()); | |
header.font = Font.mediumSystemFont(10); | |
if (incidenceData) { | |
localIncedence = incidenceData.local; | |
germanIncedence = incidenceData.germany; | |
let incedenceText = ''; | |
if(localIncedence){ | |
incedenceText += localIncedence.value; | |
} | |
if(localIncedence && germanIncedence){ | |
incedenceText += ' / '; | |
} | |
if(germanIncedence){ | |
incedenceText += germanIncedence.value; | |
} | |
label = list.addText(incedenceText); | |
label.font = Font.mediumSystemFont(22); | |
if(localIncedence && germanIncedence){ | |
label.font = Font.mediumSystemFont(17); | |
} | |
if(germanIncedence){ | |
if (germanIncedence.value >= 50) { | |
label.textColor = Color.red(); | |
} else if (germanIncedence.value >= 25) { | |
label.textColor = Color.orange(); | |
} else if (germanIncedence.value < 25) { | |
label.textColor = Color.green(); | |
} | |
if (germanIncedence.shouldCache) { | |
list.refreshAfterDate = new Date(Date.now() + 60 * 60 * 1000); | |
} | |
} | |
let locationString = 'Deutschland'; | |
if(localIncedence){ | |
if (localIncedence.value >= 50) { | |
label.textColor = Color.red(); | |
} else if (localIncedence.value >= 25) { | |
label.textColor = Color.orange(); | |
} else if (localIncedence.value < 25) { | |
label.textColor = Color.green(); | |
} | |
locationString = localIncedence.areaName+' / Deutschland'; | |
if (localIncedence.shouldCache) { | |
list.refreshAfterDate = new Date(Date.now() + 60 * 60 * 1000); | |
} | |
} | |
const city = list.addText(locationString); | |
city.font = Font.mediumSystemFont(10); | |
city.textColor = Color.gray(); | |
} else { | |
list.addText("Daten nicht verfügbar"); | |
} | |
list.addSpacer(); | |
// fetch new vaccines | |
const number = await getVaccineData(); | |
console.log(number); | |
let amount = number.value.toLocaleString(); | |
console.log(amount); | |
header = list.addText("💉 " + amount); | |
header.font = Font.mediumSystemFont(10); | |
header.textColor = Color.gray() | |
return list; | |
} | |
// Get vaccine Status | |
async function getVaccineData() { | |
let data = await new Request(vaccineStatus).loadJSON(); | |
const attr = data.vaccinated; | |
return { | |
value: attr, | |
}; | |
} | |
async function getNewCasesData() { | |
let data = await new Request(newCasesApiUrl).loadJSON(); | |
const attr = data.features[0].attributes; | |
return { | |
value: attr.value, | |
areaName: "Deutschland", | |
shouldCache: false, | |
}; | |
} | |
async function getIncidenceData() { | |
try { | |
let result = { local: null, germany: null}; | |
const location = await getLocation(); | |
if (location) { | |
let data = await new Request(incidenceUrl(location)).loadJSON(); | |
const attr = data.features[0].attributes; | |
result.local = { | |
value: attr.cases7_per_100k.toFixed(1), | |
areaName: attr.GEN, | |
shouldCache: true, | |
}; | |
} | |
let data = await new Request(incidenceUrlStates).loadJSON(); | |
const incidencePerState = data.features.map( | |
(f) => f.attributes.cases7_bl_per_100k | |
); | |
const averageIncidence = | |
incidencePerState.reduce((a, b) => a + b) / incidencePerState.length; | |
result.germany = { | |
value: averageIncidence.toFixed(1), | |
areaName: "Deutschland", | |
shouldCache: false, | |
}; | |
console.log(result); | |
return result; | |
} catch (e) { | |
console.log(e); | |
return null; | |
} | |
} | |
async function getLocation() { | |
try { | |
if (args.widgetParameter) { | |
const fixedCoordinates = args.widgetParameter.split(",").map(parseFloat); | |
return { latitude: fixedCoordinates[0], longitude: fixedCoordinates[1] }; | |
} else { | |
Location.setAccuracyToThreeKilometers(); | |
return await Location.current(); | |
} | |
} catch (e) { | |
return null; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment