Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
COVID-19 Inzidenz-Widget für iOS innerhalb Deutschlands 🇩🇪
// 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
const locationApi = (location) => `https://services7.arcgis.com/mOBPykOjAyBO2ZKk/arcgis/rest/services/RKI_Landkreisdaten/FeatureServer/0/query?where=1%3D1&outFields=OBJECTID,cases7_per_100k,cases7_bl_per_100k,cases,GEN,county,BL,last_update&geometry=${location.longitude.toFixed(3)}%2C${location.latitude.toFixed(3)}&geometryType=esriGeometryPoint&inSR=4326&spatialRel=esriSpatialRelWithin&returnGeometry=false&outSR=4326&f=json`
const serverApi = (landkreisId) => `https://cdn.marcelrebmann.de/corona/?id=${landkreisId}`
const VACCINATION_IMG_URL = `https://cdn.marcelrebmann.de/img/vaccine-64.png`
/**
* User specific configuration.
* Change the parameters, as you prefer.
*
* - isInfectionsWidgetCentered:
* Controls the content alignment of the "INF" widgetmode
* true -> The widget content is displayed centered
* false -> The widget content is displayed left aligned
*
* - location_cache_filename:
* This specifies the file where the widget caches the last retrieved location data.
* This is only relevant, if the location is not fixed via widget parameters.
*/
const CONFIG = {
isInfectionsWidgetCentered: true,
location_cache_filename: "corona_location.txt",
data_cache_filename: "corona_widget_data.txt",
vaccination_image_filename: "vaccine-64.png"
}
const WIDGET_MODE = {
INCIDENCE: "INCIDENCE",
INFECTIONS: "INFECTIONS"
}
const WIDGET_SIZE_MEDIUM = "medium"
const INCIDENCE_YELLOW = 35
const INCIDENCE_RED = 50
const INCIDENCE_MAGENTA = 200
const COLOR_MAGENTA = new Color("#db0080")
const COLOR_DARK_BG = new Color("#1c1c1d")
const COLOR_VACCINATION = new Color("#2196f3")
const INCIDENCE_HEADER = `🦠 INZIDENZ`
const INFECTIONS_HEADER = `🦠 INFEKTIONEN`
const BUNDESLAENDER_SHORT = {
'Baden-Württemberg': 'BW',
'Bayern': 'BY',
'Berlin': 'BE',
'Brandenburg': 'BB',
'Bremen': 'HB',
'Hamburg': 'HH',
'Hessen': 'HE',
'Mecklenburg-Vorpommern': 'MV',
'Niedersachsen': 'NI',
'Nordrhein-Westfalen': 'NRW',
'Rheinland-Pfalz': 'RP',
'Saarland': 'SL',
'Sachsen': 'SN',
'Sachsen-Anhalt': 'ST',
'Schleswig-Holstein': 'SH',
'Thüringen': 'TH'
}
class Cache {
static init() {
Cache.fileManager = FileManager.local()
Cache.dataCacheFilePath = Cache.fileManager.joinPath(Cache.fileManager.documentsDirectory(), CONFIG.data_cache_filename)
Cache.locationCacheFilePath = Cache.fileManager.joinPath(Cache.fileManager.documentsDirectory(), CONFIG.location_cache_filename)
Cache.vaccinationImageFilePath = Cache.fileManager.joinPath(Cache.fileManager.documentsDirectory(), CONFIG.vaccination_image_filename)
}
static getLocationHash(location) {
return `${location.latitude.toFixed(3)}-${location.longitude.toFixed(3)}`
}
/**
* Loads cached data for a location (lat-lon)
* @param location
*/
static get(location) {
const locationHash = Cache.getLocationHash(location)
const cacheExists = Cache.fileManager.fileExists(Cache.dataCacheFilePath)
if (!cacheExists) {
return null
}
const fileContents = Cache.fileManager.readString(Cache.dataCacheFilePath)
try {
const cachedData = JSON.parse(fileContents)
return cachedData[locationHash]
} catch {
return null
}
}
/**
* Updates the cached data for a given location (lat-lon)
*/
static update(location, data) {
if (!location || !location.latitude || !location.longitude || !data) {
return;
}
const locationHash = Cache.getLocationHash(location)
const cacheExists = Cache.fileManager.fileExists(Cache.dataCacheFilePath)
let fileContents;
let cachedData = {}
if (cacheExists) {
fileContents = Cache.fileManager.readString(Cache.dataCacheFilePath)
}
if (fileContents) {
cachedData = JSON.parse(fileContents)
}
cachedData[locationHash] = data
Cache.fileManager.writeString(Cache.dataCacheFilePath, JSON.stringify(cachedData))
}
static async loadVaccinationImage() {
if (Cache.fileManager.fileExists(Cache.vaccinationImageFilePath)) {
return Cache.fileManager.readImage(Cache.vaccinationImageFilePath)
}
try {
const image = await new Request(VACCINATION_IMG_URL).loadImage()
Cache.fileManager.writeImage(Cache.vaccinationImageFilePath, image)
return loadedImage
} catch {
console.log("[CACHE] could not load vaccination image")
return;
}
}
}
Cache.init()
class Utils {
static isNumericValue(number) {
return number || number === 0
}
static shortFormatNumber(number) {
if (number < 10000) {
return `${number}`
} else if (number < 1000000) {
return `${number % 1000 >= 100 ? (number / 1000).toFixed(1) : Math.floor(number / 1000)}k`.replace(".", ",")
} else {
return `${number % 1000000 >= 100000 ? (number / 1000000).toFixed(1) : Math.floor(number / 1000000)}M`.replace(".", ",")
}
}
static parseRkiDate(dateString) {
const match = dateString.match(/^([0-9]{2}).([0-9]{2}).([0-9]{4})/);
if (!match || !match.length) {
return null;
}
const day = match[1];
const month = match[2];
const year = match[3];
return new Date(year, `${parseInt(month) - 1}`, day);
}
static getNextUpdate(data) {
if (!data || !data.rki_updated || !data.landkreis || !data.landkreis.cases7_per_100k_trend || !data.vaccination.last_updated) {
return null
}
const last_updated = new Date(data.rki_updated)
const vaccination_last_updated = new Date(data.vaccination.last_updated)
last_updated.setDate(last_updated.getDate() + 1)
last_updated.setHours(0)
vaccination_last_updated.setDate(vaccination_last_updated.getDate() + 1)
vaccination_last_updated.setHours(0)
vaccination_last_updated.setMinutes(0)
vaccination_last_updated.setSeconds(0)
const moreRecent = Math.min(last_updated.getTime(), vaccination_last_updated.getTime())
return moreRecent > Date.now() ? new Date(moreRecent) : null
}
}
class UiHelpers {
static getIncidenceColor(incidence) {
if (incidence >= INCIDENCE_MAGENTA) {
return COLOR_MAGENTA
} else if (incidence >= INCIDENCE_RED) {
return Color.red()
} else if (incidence >= INCIDENCE_YELLOW) {
return Color.orange()
} else {
return Color.green()
}
}
static getInfectionTrend(slope) {
if (slope >= 1) {
return "▲"
} else if (slope >= 0) {
return "▶︎"
} else if (slope < 0) {
return "▼"
} else {
return "-"
}
}
static getTrendColor(slope) {
if (slope > 4) {
return Color.red()
} else if (slope >= 1) {
return Color.orange()
} else if (slope < 0) {
return Color.green()
} else {
return Color.gray()
}
}
static generateLandkreisName(data, customLandkreisName) {
if (customLandkreisName) {
return customLandkreisName
}
return data.landkreis.county.match(/^SK \w+$/) ? `${data.landkreis.GEN} (SK)` : data.landkreis.GEN
}
static generateDataState(data) {
if (!data.rki_updated) {
return `Stand: ${(data.landkreis.last_update || "").substr(0, 10)}`
}
const date = new Date(data.rki_updated)
const day = date.getDate()
const month = date.getMonth() + 1
const year = date.getFullYear()
return `Stand: ${day < 10 ? '0' : ''}${day}.${month < 10 ? '0' : ''}${month}.${year}`
}
static generateFooter(widget, incidence, predictedIncidenceSlope, labelText, isCentered) {
const footer = widget.addStack()
footer.layoutHorizontally()
footer.useDefaultPadding()
footer.centerAlignContent()
if (isCentered) {
footer.addSpacer()
}
const incidenceLabel = footer.addText(Utils.isNumericValue(incidence) ? `${incidence.toFixed(1).replace(".", ",")}` : "-")
incidenceLabel.font = Font.boldSystemFont(12)
incidenceLabel.textColor = UiHelpers.getIncidenceColor(incidence)
const trendIconLabel = footer.addText(` ${UiHelpers.getInfectionTrend(predictedIncidenceSlope)}`)
trendIconLabel.font = Font.systemFont(12)
trendIconLabel.textColor = UiHelpers.getTrendColor(predictedIncidenceSlope)
const label = footer.addText(labelText)
label.font = Font.systemFont(12)
label.textColor = Color.gray()
if (isCentered) {
footer.addSpacer()
}
}
static generateVaccinationInfo(widget, vaccinationImage, vaccinationQuote, vaccinationDelta, lastUpdated, isCentered) {
const vaccinationInfo = widget.addStack()
vaccinationInfo.centerAlignContent()
if (isCentered) {
vaccinationInfo.addSpacer()
}
const vaccPercent = vaccinationInfo.addText(`${Utils.isNumericValue(vaccinationQuote) ? `${vaccinationQuote.toFixed(1).replace(".", ",")}` : "-"}% `)
vaccPercent.font = Font.boldSystemFont(12)
vaccPercent.textColor = COLOR_VACCINATION
if (vaccinationImage) {
const vaccIcon = vaccinationInfo.addImage(vaccinationImage)
vaccIcon.imageSize = new Size(10, 10)
}
const vaccDelta = vaccinationInfo.addText(Utils.isNumericValue(vaccinationDelta) ? ` (+${Utils.shortFormatNumber(vaccinationDelta)})` : "")
vaccDelta.font = Font.systemFont(12)
vaccDelta.textColor = Color.gray()
const dataTime = new Date(lastUpdated)
dataTime.setDate(dataTime.getDate() + 1)
dataTime.setHours(0)
dataTime.setMinutes(0)
dataTime.setSeconds(0)
if (Date.now() > dataTime.getTime()) {
vaccinationInfo.addText(" ")
const icon = SFSymbol.named("exclamationmark.arrow.circlepath")
const outdatedIndicator = vaccinationInfo.addImage(icon.image)
outdatedIndicator.imageSize = new Size(12, 12)
outdatedIndicator.tintColor = Color.gray()
}
if (isCentered) {
vaccinationInfo.addSpacer()
}
}
}
async function loadData(location, isLocationFlexible) {
const cachedData = isLocationFlexible ? undefined : Cache.get(location)
let rkiObjectId;
let rkiData;
if (!cachedData || !cachedData.landkreis) {
rkiData = await new Request(locationApi(location)).loadJSON()
const isRkiDataValid = rkiData && rkiData.features && rkiData.features.length && rkiData.features[0].attributes
if (!isRkiDataValid) {
return null
}
rkiObjectId = rkiData.features[0].attributes.OBJECTID
} else {
rkiObjectId = cachedData.landkreis.OBJECTID
}
const apiData = await new Request(serverApi(rkiObjectId)).loadJSON()
try {
if (!apiData && !cachedData) {
throw "No data - use RKI fallback data without trend"
}
if (!apiData && !!cachedData) {
return cachedData
}
const isCacheUpdateNeeded = !isLocationFlexible && (!cachedData || apiData.rki_updated > (cachedData.rki_updated || 0))
if (isCacheUpdateNeeded) {
Cache.update(location, apiData)
}
return apiData
} catch {
return {
landkreis: {
...rkiData.features[0].attributes,
cases7_per_100k_trend: {},
cases7_bl_per_100k_trend: {}
},
country: {
cases7_de_per_100k_trend: {}
}
}
}
}
async function loadAbsoluteCases() {
const data = await new Request(serverApi(1)).loadJSON()
if (!data) {
return null
}
return data
}
async function loadSavedLocation() {
const doesCachedFileExist = Cache.fileManager.fileExists(Cache.locationCacheFilePath)
if (!doesCachedFileExist) {
return null
}
const fileContents = Cache.fileManager.readString(Cache.locationCacheFilePath)
try {
const savedLoc = JSON.parse(fileContents)
if (!savedLoc || !savedLoc.latitude || !savedLoc.longitude) {
return null
}
return savedLoc
} catch {
return null
}
}
async function loadLocation() {
const lastKnownLocation = await loadSavedLocation()
try {
Location.setAccuracyToThreeKilometers()
const location = await Location.current()
if (!location) {
throw "No data from fetching location"
}
if (!lastKnownLocation || location.latitude !== lastKnownLocation.latitude || location.longitude !== lastKnownLocation.longitude) {
Cache.fileManager.writeString(Cache.locationCacheFilePath, JSON.stringify(location))
}
return location
} catch {
return {
...lastKnownLocation,
isCached: true
}
}
}
const createIncidenceWidget = (widget, data, customLandkreisName, isLocationFlexible, isCached, isMediumSizedWidget, vaccinationImage) => {
const headerStack = widget.addStack()
headerStack.layoutHorizontally()
headerStack.centerAlignContent()
const header = headerStack.addText(INCIDENCE_HEADER)
header.font = Font.mediumSystemFont(13)
if (isLocationFlexible) {
headerStack.addSpacer(isMediumSizedWidget ? 10 : null)
const icon = SFSymbol.named(isCached ? "bolt.horizontal.circle" : "location")
const flexibleLocationIndicator = headerStack.addImage(icon.image)
flexibleLocationIndicator.imageSize = new Size(14, 14)
flexibleLocationIndicator.tintColor = isCached ? Color.gray() : Color.blue()
}
widget.addSpacer()
if (!data) {
widget.addText("Keine Ergebnisse für den aktuellen Ort gefunden.")
return;
}
const mainContent = widget.addStack()
mainContent.layoutHorizontally()
mainContent.useDefaultPadding()
mainContent.centerAlignContent()
const isLandkreisIncidenceToBeShortened = Utils.isNumericValue(data.landkreis.cases7_per_100k) && data.landkreis.cases7_per_100k >= 1000;
const landkreisIncidence = data.landkreis.cases7_per_100k.toFixed(isLandkreisIncidenceToBeShortened ? 0 : 1)
const incidenceLabel = mainContent.addText(Utils.isNumericValue(data.landkreis.cases7_per_100k) ? `${landkreisIncidence.replace(".", ",")}` : "-")
incidenceLabel.font = Font.boldSystemFont(24)
incidenceLabel.textColor = UiHelpers.getIncidenceColor(data.landkreis.cases7_per_100k)
const landkreisTrendIconLabel = mainContent.addText(` ${UiHelpers.getInfectionTrend(data.landkreis.cases7_per_100k_trend.slope)}`)
landkreisTrendIconLabel.font = Font.systemFont(14)
landkreisTrendIconLabel.textColor = UiHelpers.getTrendColor(data.landkreis.cases7_per_100k_trend.slope)
const casesLandkreisIncrease = Utils.isNumericValue(data.landkreis.cases) && Utils.isNumericValue(data.landkreis.cases_previous_day) ? data.landkreis.cases - data.landkreis.cases_previous_day : undefined
const casesLandkreisLabel = mainContent.addText(` (${Utils.isNumericValue(casesLandkreisIncrease) ? `${casesLandkreisIncrease >= 0 ? "+" : ""}${casesLandkreisIncrease.toLocaleString()}` : "-"})`)
casesLandkreisLabel.font = Font.systemFont(data.landkreis.cases7_per_100k >= 100 && Math.abs(casesLandkreisIncrease) >= 100 ? 10 : 14)
casesLandkreisLabel.textColor = Color.gray()
const landkreisNameLabel = widget.addText(UiHelpers.generateLandkreisName(data, customLandkreisName))
landkreisNameLabel.minimumScaleFactor = 0.7
widget.addSpacer()
UiHelpers.generateFooter(widget, data.landkreis.cases7_bl_per_100k, data.landkreis.cases7_bl_per_100k_trend.slope, ` ${BUNDESLAENDER_SHORT[data.landkreis.BL]}`)
UiHelpers.generateVaccinationInfo(
widget,
vaccinationImage,
data.vaccination.state.vacc_quote,
data.vaccination.state.vacc_delta,
data.vaccination.last_updated,
false)
const stateInfo = widget.addText(UiHelpers.generateDataState(data))
stateInfo.font = Font.systemFont(10)
stateInfo.textColor = Color.gray()
}
const createInfectionsWidget = (widget, data, vaccinationImage) => {
const headerLabel = widget.addText(INFECTIONS_HEADER)
headerLabel.font = Font.mediumSystemFont(13)
if (!data) {
widget.addText("Keine Fallzahlen verfügbar.")
return;
}
const countryData = data.country
const infectionsDiff = countryData.new_cases - countryData.new_cases_previous_day
widget.addSpacer()
widget.addSpacer(1)
const casesStack = widget.addStack()
if (CONFIG.isInfectionsWidgetCentered) {
casesStack.addSpacer()
}
const casesLabel = casesStack.addText(`${Utils.isNumericValue(countryData.new_cases) ? countryData.new_cases.toLocaleString() : "-"}`)
casesLabel.font = Font.boldSystemFont(24)
casesLabel.minimumScaleFactor = 0.8
if (CONFIG.isInfectionsWidgetCentered) {
casesStack.addSpacer()
}
const casesDifferenceStack = widget.addStack()
if (CONFIG.isInfectionsWidgetCentered) {
casesDifferenceStack.addSpacer()
}
const casesTrendIcon = casesDifferenceStack.addText(UiHelpers.getInfectionTrend(countryData.new_cases - countryData.new_cases_previous_day))
casesTrendIcon.font = Font.systemFont(14)
casesTrendIcon.textColor = UiHelpers.getTrendColor(infectionsDiff)
const casesDiffLabel = casesDifferenceStack.addText(Utils.isNumericValue(infectionsDiff) ? ` (${infectionsDiff >= 0 ? '+' : ''}${infectionsDiff.toLocaleString()})` : "-")
casesDiffLabel.font = Font.systemFont(14)
casesDiffLabel.textColor = Color.gray()
if (CONFIG.isInfectionsWidgetCentered) {
casesDifferenceStack.addSpacer()
}
widget.addSpacer()
const deTrendSlope = countryData.cases7_de_per_100k_trend ? countryData.cases7_de_per_100k_trend.slope : countryData.cases7_de_per_100k_trend
UiHelpers.generateFooter(widget, countryData.cases7_de_per_100k, deTrendSlope, " DE", CONFIG.isInfectionsWidgetCentered)
UiHelpers.generateVaccinationInfo(
widget,
vaccinationImage,
data.vaccination.country.vacc_quote,
data.vaccination.country.vacc_delta,
data.vaccination.last_updated,
CONFIG.isInfectionsWidgetCentered)
widget.addSpacer(2)
const stateInfo = widget.addStack()
if (CONFIG.isInfectionsWidgetCentered) {
stateInfo.addSpacer()
}
const updateLabel = stateInfo.addText(UiHelpers.generateDataState(data))
updateLabel.font = Font.systemFont(10)
updateLabel.textColor = Color.gray()
if (CONFIG.isInfectionsWidgetCentered) {
stateInfo.addSpacer()
}
}
let widget = await createWidget(config.widgetFamily)
if (!config.runsInWidget) {
await widget.presentMedium()
}
Script.setWidget(widget)
Script.complete()
async function createWidget(size) {
const isMediumSizedWidget = size === WIDGET_SIZE_MEDIUM
let location = {};
let customLandkreisName;
let widgetMode = WIDGET_MODE.INCIDENCE;
const params = args.widgetParameter ? args.widgetParameter.split(",") : undefined
// const params = ["49.89", "10.855"] // BA
// const params = ["48.6406978", "9.1391464"] // Böblingen
const widget = new ListWidget()
widget.backgroundColor = Color.dynamic(Color.white(), COLOR_DARK_BG)
if (!params) {
location = await loadLocation()
if (!location) {
widget.addText("Standort konnte nicht ermittelt werden.")
return widget
}
}
if (params && params[0] === "INF") {
widgetMode = WIDGET_MODE.INFECTIONS
}
if (params && params[0] !== "INF") {
location = {
latitude: parseFloat(params[0]),
longitude: parseFloat(params[1])
}
customLandkreisName = params[2]
}
const isLocationFlexible = !params
const vaccinationImage = await Cache.loadVaccinationImage()
if (isMediumSizedWidget) {
if (widgetMode === WIDGET_MODE.INFECTIONS) {
const infectionData = await loadAbsoluteCases()
createInfectionsWidget(widget, infectionData, vaccinationImage)
if (infectionData) {
widget.refreshAfterDate = Utils.getNextUpdate(infectionData)
}
return widget
}
const data = await loadData(location, isLocationFlexible)
CONFIG.isInfectionsWidgetCentered = false
const main = widget.addStack()
const l = main.addStack()
l.layoutVertically()
createIncidenceWidget(l, data, customLandkreisName, isLocationFlexible, location.isCached, isMediumSizedWidget, vaccinationImage)
main.addSpacer()
main.addSpacer(40)
main.addSpacer()
const r = main.addStack()
r.layoutVertically()
createInfectionsWidget(r, data, vaccinationImage)
if (data) {
widget.refreshAfterDate = Utils.getNextUpdate(data)
}
return widget
}
switch (widgetMode) {
case WIDGET_MODE.INCIDENCE:
const data = await loadData(location, isLocationFlexible)
createIncidenceWidget(widget, data, customLandkreisName, isLocationFlexible, location.isCached, isMediumSizedWidget, vaccinationImage)
if (data) {
widget.refreshAfterDate = Utils.getNextUpdate(data)
}
break;
case WIDGET_MODE.INFECTIONS:
const infectionData = await loadAbsoluteCases()
createInfectionsWidget(widget, infectionData, vaccinationImage)
if (infectionData) {
widget.refreshAfterDate = Utils.getNextUpdate(infectionData)
}
break;
default:
widget.addText("Keine Daten.")
}
return widget
}
@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 19, 2020

WICHTIG: MIGRATION ZU GITHUB REPO

Zur besseren Verwaltung habe ich das Skript in ein GitHub-Repository umgezogen: https://github.com/marcelrebmann/corona-widget-ios. Zukünftige Updates und alles andere werden ab nun dort bereitgestellt! 🙃

Aktueller Stand

Update 11.01.2021

Impfquoten für Bundesländer und Deutschland werden angezeigt (Datenquelle: RKI).

  • Prozentuale Anzeige der Impfungen im jeweiligen Bundesland bzw. in Deutschland (INF-Modus)
  • Zunahme im Vergleich zum Vortag
  • Indikator (Ausrufezeichen mit Pfeil) zur Info, falls nur "veraltete" Impfdaten zur Verfügung stehen (Die Daten werden vom RKI nur werktags aktualisiert).

Update 28.12.2020

Behebt ein Problem, bei dem gelegentlich (oftmals morgens) keine Daten angezeigt wurden - vermutlich aufgrund starker Auslastung der RKI API.

  • Caching der zuletzt abgefragten Daten lokal auf dem Gerät. Falls keine Daten geladen werden können, werden diese angezeigt.
  • Verbesserung der Effizienz durch weniger Aktualisierungen im Hintergrund.

Update 08.12.2020

  • Neue Farbe (dunkles Magenta) bei Inzidenzen über dem 200er Grenzwert.
  • Die Medium-Größe des Scriptable Widgets wird nun auch unterstützt.

Update 07.11.2020

  • Das Infektionen (INF) Widget kann wahlweise zentriert oder linksbündig angezeigt werden.
    Einstellbar über die Konfigurations-Variable CONFIG. isInfectionsWidgetCentered
  • Die Hintergrundfarbe im Dark Mode ist jetzt nicht mehr komplett schwarz, sondern gleicht der anderer Apple-Widgets (beispielsweise dem Kalender-Widget)
  • Stadtkreise werden nun mit (SK) annotiert, um mehr Platz zu schaffen.

Update 24.10.2020 - Trends sind jetzt verfügbar!

Die Trends basieren auf dem Verlauf der jeweiligen Inzidenzwerte der letzten 7 Tage für den ausgewählten Stand-/Landkreis/Bundesland/Deutschland
Symbollegende:

  • ▲ = steigend (Farben: 🔴. = starker Anstieg, 🟠 = moderater Anstieg)
  • ▶︎ = gleichbleibend (Farbe: grau)
  • ▼ = fallend (Farbe: 🟢 )

Inzidenz-Modus

  • 7-Tages Inzidenz für Landkreis + Bundesland
  • Anstieg der absoluten Fallzahlen im Landkreis im vgl. zum vorherigen Tag
  • Info zur Aktualität der Daten (RKI)
  • Kreisfreie Städte werden mit (Stadt) unterschieden
  • Der Landkreis-Name kann durch ein eigenes Label überschrieben werden
  • Impfquote für Bundesland und Anstieg der Impfungen im Vergleich zum Vortag

IMG_9D54F3D9D555-1

Widget Parameter

Der Ort wird mittels Längen- und Breitengrad konfiguriert.
Falls gewünscht, kann als dritter Parameter noch eine eigene Bezeichnung für den Landkreis angegeben werden.

Latitude,Longitude,Landkreis-Label (Optional)
Bsp:
49.88,12.68,Arbeit

Fallzahlen-Modus

Da ich gerne noch die Neuinfektionen und einen Trend möchte, habe ich diesen Modus zusätzlich implementiert.

  • Neuinfektionen des vorherigen Tages
  • Veränderung der gestrigen Neuinfektionen im Vergleich zum Vortag ("Gestern waren es X Neuinfektionen mehr, als vorgestern")
  • 7-Tage-Inzidenz für Deutschland + Trend
  • Impfquoten für Deutschland

Die Trenddaten werden über eine API, die auf meinem Server bereitgestellt ist, bezogen und angezeigt.
Die Server-API fragt periodisch die RKI-Daten mit den Fallzahlen der Bundesländer von ArcGis (https://npgeo-corona-npgeo-de.hub.arcgis.com/datasets/ef4b445a53c1406892257fe63129a8ea_0/geoservice?geometry=-30.896%2C46.270%2C47.151%2C55.886) ab und hält die Werte der letzten Woche vor. Spätestens etwa eine halbe Stunde, nachdem die Daten vom RKI aktualisiert wurden, sollten diese auch im Widget sichtbar sein.

IMG_5DF9BB37DC0A-1
Um das Widget linksbündig anzuzeigen, muss in der CONFIG isInfectionsWidgetCentered auf false gesetzt werden
IMG_0206

Widget Parameter

Um diesen Modus zu aktivieren, muss INF als Parameter eingegeben werden.

Medium-Widget

IMG_0324

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

Die Anleitung zur Installation findet sich hier in den Kommentaren:
https://gist.github.com/kevinkub/46caebfebc7e26be63403a7f0587f664

@Gandalf8266

This comment has been minimized.

Copy link

@Gandalf8266 Gandalf8266 commented Oct 20, 2020

Hallo, tolle Sache mit der Ampel,
kannst du das Skript dahingehend erweitern, dass bei dem Parameter ein 3 Parameter übergeben werden kann, welche ein Label ist.
Hintergrund:
Bei Regensburg gibt es die Stadt Regensburg und den Landkreis Regensburg, aber als Label (wo bei dir Bamberg steht) wird immer nur Regensburg angezeigt.
Die Lösung wäre eben, dass als Parameter, wo die Längen- und Breitengrade angezeigt werden, zusätzlich ein Label angegeben werden kann, Beispiel: 49.01,12.1, Regensburg Stadt
IMG_8473

vielen Dank
vg
Christian

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

Hi Christian,

danke für den guten Punkt, das ist bei Bamberg auch so ;)
Habe das Skript geupdated.
Stadtkreise (wie z.B. Regensburg, ...) sind jetzt ersichtlich - ohne zusätzliche Parameter.

Lg

2089D774-B3D8-4E6B-8EC2-940C4074B730

@Gandalf8266

This comment has been minimized.

Copy link

@Gandalf8266 Gandalf8266 commented Oct 20, 2020

Hallo Marcel,
danke für die schelle Umsetzung, sieht sehr gut aus.
Gleichzeitig fände ich es trotzdem noch hilfreich, wenn ich zusätzlich ein eigenes Label als 3. Parameter hinzufügen könnte.
Mir fallen da 3 Use-Cases ein:

  1. Wenn man im Landkreis wohnt, könnte man seinen Wohnort hinzufügen
  2. Man könnte als Label "zu Hause" oder "Arbeit" hinzufügen
  3. Wenn ich das Widget auch ohne Parameter behalten will um den Wert vom aktuellen Ort zu wissen, muss habe ich das Widget 2 mal unter dem gleichen Namen drin, wenn ich mich zu Hause befinde.

vg
Christian

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

Hab einige Dinge geändert:

  • Absolute Fallzahlen für Bundesland hinzugefügt
  • Farbige Zahl für das Bundesland
  • Länderkürzel statt ganzen Bundesland-Namen
  • Info zur Aktualität der Daten eingefügt
  • Als dritter Parameter kann (muss nicht) ein eigener Name für den Landkreis eingegeben werden, der den Standardnamen dann überschreibt: Beispiel (49.02,16.02,Home)

73F0055E-681D-4D55-9D7A-D11F9F7B972D

@TiiFuchs

This comment has been minimized.

Copy link

@TiiFuchs TiiFuchs commented Oct 20, 2020

Würde dir auch empfehlen den

    if (Device.isUsingDarkAppearance()) {
        list.backgroundGradient = getDarkGradient()
    }

Code rauszunehmen, da dieser von Scriptable in Widgets nicht unterstützt wird und dann manchmal diese Farbprobleme verursacht, wenn man im Lightmode ist und der Hintergrund plötzlich geändert wird.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

Würde dir auch empfehlen den

    if (Device.isUsingDarkAppearance()) {
        list.backgroundGradient = getDarkGradient()
    }

Code rauszunehmen, da dieser von Scriptable in Widgets nicht unterstützt wird und dann manchmal diese Farbprobleme verursacht, wenn man im Lightmode ist und der Hintergrund plötzlich geändert wird.

Danke für den Reminder! Ist raus 👍

@bobynator93

This comment has been minimized.

Copy link

@bobynator93 bobynator93 commented Oct 20, 2020

0BCBDA68-1103-42B6-A69A-C07727450EF6
Hat sich etwas geändert? "Stadt" wird nicht mehr dargestellt, nur noch "..."

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

0BCBDA68-1103-42B6-A69A-C07727450EF6
Hat sich etwas geändert? "Stadt" wird nicht mehr dargestellt, nur noch "..."

Bei den Max-iPhones passt das "Stadt" noch drauf und wird umgebrochen, da das Widget hier leicht größer scheint.
Sollte jetzt aber gefixed sein! :)

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 20, 2020

0BCBDA68-1103-42B6-A69A-C07727450EF6
Hat sich etwas geändert? "Stadt" wird nicht mehr dargestellt, nur noch "..."

Danke dafür . Wo finde ich den Code der zu diesem Bild führt ? (Der oben zeigt noch die kugeln an )

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

@F3000 der obige Code führt zu dem Widget, das du meinst. Die Kugeln waren noch ungenutze Altlasten im Code (die sind mittlerweile raus).
Lg

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 20, 2020

Hab’s gefunden . Danke ;)

Letzte Frage :

Wie bekomme ich den Landkreis Namen kleiner in der Schriftgröße ?

C1A97667-90C3-44B2-9BE0-F7322B154A7C

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 20, 2020

@F3000 um die Schriftgröße zu ändern, müsstest du list.addText(landkreisName) (Zeile 102) als Variable speichern und dann die Schriftgröße setzen.
Beispiel:

const name = list.addText(landkreisName);
name.font = Font.systemFont(14) // z.B. Schriftgröße 14
@Gandalf8266

This comment has been minimized.

Copy link

@Gandalf8266 Gandalf8266 commented Oct 21, 2020

wenn man den Schriftgröße ändert, sollte man auch den die Schriftgröße bei Stadt anpassen, zwecks der Optik :-)
ich habe die Zeile 105 z.B. so angepasst:
const stname = list.addText('(Stadt)')
stname.font = Font.systemFont(14)

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 21, 2020

Hi!
Ich bin durch Zufall über diese Seite gestolpert. Das Script ist wirklich eine tolle Sache und optisch auch schön anzusehen. Ich selbst bin kein Programmierer, daher meine Frage:
Ist es auf einfachem Wege möglich, bei längeren Kreisnamen, die nicht in voller Länge angezeigt werden können, einen Zeilenumbruch zu erzwingen? Das würde dann neben anderen Widges gleichmäßiger aussehen und nicht, wie jetzt, verschoben. Als Beispiel habe ich ein Screenshot angehängt.
9374247B-C803-41C4-BEEB-BDB0A3EA9347

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 21, 2020

@QWERTZ000
Mit dem aktuellsten Code habe ich die Schriftgröße etwas flexibler gemacht. Jetzt sollte der Text umbrechen und zwei Zeilen beanspruchen, falls nötig. (Getestet auf einem iPhone X (5,8" Display))
Gib gerne Rückmeldung, ob das bei dir auch funktioniert hat.
Alternativ hast du auch immer die Möglichkeit, eine eigene Bezeichnung für den Landkreis als Widget Parameter (siehe erster Kommentar oben) anzugeben!

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 21, 2020

@QWERTZ000
Mit dem aktuellsten Code habe ich die Schriftgröße etwas flexibler gemacht. Jetzt sollte der Text umbrechen und zwei Zeilen beanspruchen, falls nötig. (Getestet auf einem iPhone X (5,8" Display))
Gib gerne Rückmeldung, ob das bei dir auch funktioniert hat.
Alternativ hast du auch immer die Möglichkeit, eine eigene Bezeichnung für den Landkreis als Widget Parameter (siehe erster Kommentar oben) anzugeben!

Ja, das passt jetzt besser. Durch die automatische Anpassung der Schriftgröße werden die Kreisnamen aber weiterhin in einer unterschiedlichen Höhe angezeigt (siehe Screenshot). Ich nutze ein iPhone Xs.
Abgesehen davon finden meine Widgets den ganzen Vormittag schon keine Daten mehr, wenn ich die Parameter nicht ausfülle.

BEDACDD8-55B0-4EA6-8830-FDE3D53B458F

@1121PD

This comment has been minimized.

Copy link

@1121PD 1121PD commented Oct 21, 2020

Vielen Dank, eigentlich funktioniert es bis auf das ich es mit Fehlermeldung nach einiger Zeit immer manuell wieder starten muss und:

Bei mir wird weder Stadt noch Landkreis angezeigt so wie in den Screenshots hier. Muss man da noch etwas extra angeben dafür im Script?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 21, 2020

@QWERTZ000 Die Location-Funktion ist in Widgets wohl nicht 100% zuverlässig, da manchmal der Standort nicht ermittelt werden kann. Am sichersten ist es, wenn man den Standort fix in die Parameter einträgt (siehe erster Kommentar). Für die Schriftgröße ist das mMn die beste Lösung, da die Widgets auf unterschiedlich großen Geräten mit unterschiedlich langen Namen zurechtkommen müssen.

@1121PD falls du keine Parameter im Widget angegeben hast, dann könnte das möglicherweise dein Problem lösen. In den ersten beiden Kommentaren steht mehr dazu.

@mike14-2

This comment has been minimized.

Copy link

@mike14-2 mike14-2 commented Oct 21, 2020

Hallo Marcel,

ich würde gerne wissen, ob es auch eine Möglichkeit gibt, dass man einen Verlauf darstellt, wie beim Wetter, sodass ich die Werte eines Landkreises der letzten Woche oder so sehen kann?

Vielen Dank
Mike

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 21, 2020

Ja, das denke ich auch. Man muss ja an alle Gerätegrößen denken. Vielen Dank für die Arbeit! Top!

Könntest du dir vielleicht auch vorstellen, ein weiteres Script, ähnlich dem von oliverandrich zu schreiben? Aber eben mit einer ähnlichen Anordnung der Informationen, damit es schön zusammenpasst.
Ich stelle mir folgendes vor: Zwei kleine Widgets nebeneinander. Das erste ist ein Stapel-Widget mit den einzelnen Locationen zum durchscrollen. Das zweite zeigt dann die täglichen Neuinfektionen und Inzidenz in Deutschland.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 21, 2020

@QWERTZ000
Schau dir mal den Fallzahlen-Modus (1. Kommentar, dort ist immer der aktuelle Stand beschrieben) an - damit solltest du das fast genau so haben.
Das einzige, das da fehlt, ist die Inzidenz für ganz Deutschland. Eventuell füge ich das noch in den Modus hinzu.

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 21, 2020

@QWERTZ000
Schau dir mal den Fallzahlen-Modus (1. Kommentar, dort ist immer der aktuelle Stand beschrieben) an - damit solltest du das fast genau so haben.
Das einzige, das da fehlt, ist die Inzidenz für ganz Deutschland. Eventuell füge ich das noch in den Modus hinzu.

Steht das schon länger da? Man, bin ich blind? Das schaue ich mir mal an. Danke!

@achisto

This comment has been minimized.

Copy link

@achisto achisto commented Oct 21, 2020

Hallo Marcel,

ich würde gerne wissen, ob es auch eine Möglichkeit gibt, dass man einen Verlauf darstellt, wie beim Wetter, sodass ich die Werte eines Landkreises der letzten Woche oder so sehen kann?

Vielen Dank
Mike

Vielleicht ist hierfür die App "Charty" hilfreich, die genau für sowas gedacht ist: Charts in Widgets darstellen. Ich habe die bisher allerdings nur in Kombination mit der Shortcuts-App genutzt und die Daten darüber übergeben (bzw. aus z.B. der Health-App ausgelesen), weiß daher nicht, wie gut die in Zusammenarbeit mit Scriptable funktioniert. Theoretisch ließe sich der API-Call aber sicher auch in einem Shortcut realisieren.

@JanuschM-CGN

This comment has been minimized.

Copy link

@JanuschM-CGN JanuschM-CGN commented Oct 21, 2020

Super Arbeit, Danke! Besteht die Möglichkeit, statt dem schwarzem Hintergrund (Nachtmodus) das Dunkelgrau zu bekommen, wie viele Widgets von Apple?

@achisto

This comment has been minimized.

Copy link

@achisto achisto commented Oct 21, 2020

Super Arbeit, Danke! Besteht die Möglichkeit, statt dem schwarzem Hintergrund (Nachtmodus) das Dunkelgrau zu bekommen, wie viele Widgets von Apple?

Sollte mit diesem Code aus dem Ursprungsskript gehen:

const gradient = new LinearGradient()
gradient.locations = [0, 1]
gradient.colors = [
new Color("111111"),
new Color("222222")
]
list.backgroundGradient = gradient

Um das grau zu erreichen, das du haben willst, einfach mit den Farbcodes spielen!

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 21, 2020

Hallo Marcel,
ich würde gerne wissen, ob es auch eine Möglichkeit gibt, dass man einen Verlauf darstellt, wie beim Wetter, sodass ich die Werte eines Landkreises der letzten Woche oder so sehen kann?
Vielen Dank
Mike

Vielleicht ist hierfür die App "Charty" hilfreich, die genau für sowas gedacht ist: Charts in Widgets darstellen. Ich habe die bisher allerdings nur in Kombination mit der Shortcuts-App genutzt und die Daten darüber übergeben (bzw. aus z.B. der Health-App ausgelesen), weiß daher nicht, wie gut die in Zusammenarbeit mit Scriptable funktioniert. Theoretisch ließe sich der API-Call aber sicher auch in einem Shortcut realisieren.

Mit Charty könnte das evtl gehen.
Ich kann mir aber auch vorstellen, dass es mit der WebView von Scriptable auch umsetzen kann, die dann ein SVG-Chart anzeigt. Eventuell kann man da sogar externe Libraries (z.B. d3 oder chart.js) laden und die nutzen.

@JanuschM-CGN

This comment has been minimized.

Copy link

@JanuschM-CGN JanuschM-CGN commented Oct 21, 2020

Super Arbeit, Danke! Besteht die Möglichkeit, statt dem schwarzem Hintergrund (Nachtmodus) das Dunkelgrau zu bekommen, wie viele Widgets von Apple?

Sollte mit diesem Code aus dem Ursprungsskript gehen:

const gradient = new LinearGradient()
gradient.locations = [0, 1]
gradient.colors = [
new Color("111111"),
new Color("222222")
]
list.backgroundGradient = gradient

Um das grau zu erreichen, das du haben willst, einfach mit den Farbcodes spielen!

Muss ich mal schauen, ob ich das hinbekomme - Neuland für mich :) - Danke aber schon mal. Das dunklere Grau würde sich farblich besser einfügen.

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 21, 2020

@F3000 um die Schriftgröße zu ändern, müsstest du list.addText(landkreisName) (Zeile 102) als Variable speichern und dann die Schriftgröße setzen.
Beispiel:

const name = list.addText(landkreisName);
name.font = Font.systemFont(14) // z.B. Schriftgröße 14

Wo finde ich es nun ? Zeile 137 passt bei mir nicht

Hätte noch eine Idee :
Das zweite Widget (INF) als dual Widget in Größe “Medium” zusammen mit dem ersten anzeigen

Glaube die nächste Schwelle (100 Infektionen/ in Bayern) sollte in einem nächsten Update berücksichtigt werden.

@Gandalf8266

This comment has been minimized.

Copy link

@Gandalf8266 Gandalf8266 commented Oct 22, 2020

Hallo Marcel,
ich finden deinen fork immer noch am Besten, gleichzeitig finde ich den "Tendenz-Pfeil" von dem fork auch ganz nett, den könnest du auch noch einbauen, soviel Platz wäre noch :-)

https://gist.github.com/rphl/0491c5f9cb345bf831248732374c4ef5

@Suplanus

This comment has been minimized.

Copy link

@Suplanus Suplanus commented Oct 22, 2020

Erstmal ein Dankeschön 💕
Ich würde mich auch über Tendenz zum Vortag freuen (Pfeil) aber mit +- neuen Fällen pro Landkreis und Bundesland. Evtl. mit in den Fallzahlen-Modus.

@kingmath

This comment has been minimized.

Copy link

@kingmath kingmath commented Oct 22, 2020

Erstmal ein Dankeschön 💕
Ich würde mich auch über Tendenz zum Vortag freuen (Pfeil) aber mit +- neuen Fällen pro Landkreis und Bundesland. Evtl. mit in den Fallzahlen-Modus.

An das Dankeschön möchte ich mich auch anschließen, vielen Dank für die tolle Arbeit.
Die Tendenz mittels Pfeile würde mich auch sehr interessieren.

Gibt es weiterhin die Möglichkeit die Location über eine Postleitzahl einzugeben?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 22, 2020

@F3000 Zeile 123..

@Gandalf8266 @Suplanus @kingmath Die Tendenzen habe ich auf dem Schirm, da treffe ich gerade die Vorbereitungen.
Location-Auswahl per PLZ ist aktuell noch nicht möglich, da die API vom RKI das nicht anbietet.

@1121PD

This comment has been minimized.

Copy link

@1121PD 1121PD commented Oct 22, 2020

@QWERTZ000 Die Location-Funktion ist in Widgets wohl nicht 100% zuverlässig, da manchmal der Standort nicht ermittelt werden kann. Am sichersten ist es, wenn man den Standort fix in die Parameter einträgt (siehe erster Kommentar). Für die Schriftgröße ist das mMn die beste Lösung, da die Widgets auf unterschiedlich großen Geräten mit unterschiedlich langen Namen zurechtkommen müssen.

@1121PD falls du keine Parameter im Widget angegeben hast, dann könnte das möglicherweise dein Problem lösen. In den ersten beiden Kommentaren steht mehr dazu.

Vielen Dank für Deine Antwort.
Aber dann wäre es nur ein fester Ort und nicht mehr automatisch wenn ich Parameter im Widget eingebe oder?!

Ist es normal das alle paar Stunden eine Fehlermeldung kommt und man das Script neu anstoßen muss?

@achisto

This comment has been minimized.

Copy link

@achisto achisto commented Oct 22, 2020

@F3000 Zeile 123..

@Gandalf8266 @Suplanus @kingmath Die Tendenzen habe ich auf dem Schirm, da treffe ich gerade die Vorbereitungen.
Location-Auswahl per PLZ ist aktuell noch nicht möglich, da die API vom RKI das nicht anbietet.

Für meine Arbeit mit GIS habe ich in der Vergangenheit auf die PLZ-Liste des OpenGeoDB zurückgegriffen, um PLZ mit Geokoordinaten zu matchen. Die gibt's hier als PLZ.tab und hier ist die Doku dazu zu finden. Eventuell lässt sich ja damit ein Matching herstellen? Mir fehlen leider die Skills, um sowas zu programmieren, wollte aber auf die Liste hinweisen.

@Gandalf8266

This comment has been minimized.

Copy link

@Gandalf8266 Gandalf8266 commented Oct 22, 2020

Tolle Arbeit 👍🏼👍🏼

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 22, 2020

@marcel

Danke . Hier steht bei mir folgendes :

const landkreisNameLabel = widget.addText(generateLandkreisName(data, customLandkreisName)) landkreisNameLabel.minimumScaleFactor = 0.7

Soll ich den scale Factor dann verändern ?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 22, 2020

@F3000 die Zeile landkreisNameLabel.minimumScaleFactor = 0.7 ersetzt du mit landkreisNameLabel.font = Font.systemFont(14). Die 14 ist die Schriftgröße, da kannst du verschiedene Zahlen ausprobieren, bis es für dich passt.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 22, 2020

@1121PD Wenn du die Parameter für den Standort im Widget setzt, dann ist der Ort fix, ja. Ich glaube in den anderen Forks ist das Problem mit der Location eventuell gelöst, da habe ich aber noch nicht nachgeschaut. Das hat für ich aktuell nicht die höchste Priorität, da ich an anderen Features, z.B. Trends, arbeite :)

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 22, 2020

@F3000 Zeile 123..
@Gandalf8266 @Suplanus @kingmath Die Tendenzen habe ich auf dem Schirm, da treffe ich gerade die Vorbereitungen.
Location-Auswahl per PLZ ist aktuell noch nicht möglich, da die API vom RKI das nicht anbietet.

Für meine Arbeit mit GIS habe ich in der Vergangenheit auf die PLZ-Liste des OpenGeoDB zurückgegriffen, um PLZ mit Geokoordinaten zu matchen. Die gibt's hier als PLZ.tab und hier ist die Doku dazu zu finden. Eventuell lässt sich ja damit ein Matching herstellen? Mir fehlen leider die Skills, um sowas zu programmieren, wollte aber auf die Liste hinweisen.

Das ist in der Tat ein guter Input, danke. Ich setz das mal intern auf meine Liste. Das Mapping sollte mit den dortigen Daten dann eigentlich möglich sein. 👍

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 22, 2020

@F3000 die Zeile landkreisNameLabel.minimumScaleFactor = 0.7 ersetzt du mit landkreisNameLabel.font = Font.systemFont(14). Die 14 ist die Schriftgröße, da kannst du verschiedene Zahlen ausprobieren, bis es für dich passt.

Super vielen Dank . Nun klappt soweit alles .

Danke für die bisherige Arbeit 😊

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 22, 2020

Wäre es möglich hier noch die Daten aus ganz DE anzuzeigen ? Oder ist dies für das INF Widget geplant ?

6F66D932-16C6-4A9E-A8FD-4505E579FEF1

@1121PD

This comment has been minimized.

Copy link

@1121PD 1121PD commented Oct 22, 2020

@1121PD Wenn du die Parameter für den Standort im Widget setzt, dann ist der Ort fix, ja. Ich glaube in den anderen Forks ist das Problem mit der Location eventuell gelöst, da habe ich aber noch nicht nachgeschaut. Das hat für ich aktuell nicht die höchste Priorität, da ich an anderen Features, z.B. Trends, arbeite :)

Aber was ich noch nicht verstehe ist warum funktioniert es bei manchen und bei anderen nicht?
Eigentlich ist es doch in deinem Script hinterlegt das Stadt oder Landkreis mit angezeigt wird wenn ich das richtig verstanden habe?!

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 23, 2020

Wäre es möglich hier noch die Daten aus ganz DE anzuzeigen ? Oder ist dies für das INF Widget geplant ?

6F66D932-16C6-4A9E-A8FD-4505E579FEF1

@F3000 Die Daten aus ganz DE werden eher in das Infections-Widget einfließen. Ich denke das ist eine gute Aufteilung. Der Inzidenz-Modus zeigt die Daten auf Bundesland/Landkreis-Ebene an und das Infections (INF) Widget befasst sich mit den deutschlandweiten Daten.

Im den nächsten Tagen geplant ist, das Trend-Feature (basierend auf den Zahlen der letzten 7 Tage) zu releasen, kommen in das normale Widget noch die Trend-Indikatoren für den Landkreis und das Bundesland. Dann wird der Platz schon langsam knapp, um da noch mehr anzuzeigen - es soll ja auch nicht überladen sein :)

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 23, 2020

@marcelrebmann

Hört sich gut an .

Also kommen dann in das Bundesland Widget noch kleine „Pfeile“ neben den Werten um zu sehen ob Werte gerade hoch/runter gehen ?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 24, 2020

@F3000

Trends für die Inzidenzen sind jetzt verfügbar, für Stand-/Landkreis, Bundesland und Deutschland.
Eine Erklärung der Symbole und Farblegende ist im ersten Kommentar!

Hier nochmal die aktuellen Screenshots:
IMG_278E98AD3F34-1

C3269FEF-18E9-48F3-A626-94A91CFB2E5E

@trcmk

This comment has been minimized.

Copy link

@trcmk trcmk commented Oct 24, 2020

Kann man die Absoluten Cases durch Aktive Cases tauschen?

@dersvenhesse

This comment has been minimized.

Copy link

@dersvenhesse dersvenhesse commented Oct 24, 2020

Bei Inzidenzen von über 100 im Landkreis ist die Zahl mit der einen Nachkommastelle leider zu breit und wird durch ... abgeschnitten, habe es behoben mit einer Ersetzung von toFixed(1) durch toFixed(data.landkreis.cases7_per_100k > 100 ? 0 : 1) in https://gist.github.com/marcelrebmann/64494e453deaf26cab3c14c9ff711e1e#file-incidence-js-L106.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 24, 2020

Bei Inzidenzen von über 100 im Landkreis ist die Zahl mit der einen Nachkommastelle leider zu breit und wird durch ... abgeschnitten, habe es behoben mit einer Ersetzung von toFixed(1) durch toFixed(data.landkreis.cases7_per_100k > 100 ? 0 : 1) in https://gist.github.com/marcelrebmann/64494e453deaf26cab3c14c9ff711e1e#file-incidence-js-L106.

Danke für den Hinweis! Das hab ich auf dem 6,5“ iPhone nicht gesehen. Habe es gefixed!
LG

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 24, 2020

Kann man die Absoluten Cases durch Aktive Cases tauschen?

Aktuell gibt das die API des RKI meines Wissens nach nicht her.
Im Zuge der Einführung der Trends habe ich aber die absoluten Fälle im Landkreis durch den Anstieg an absoluten Fällen ersetzt (siehe aktuelle Screenshots oben)

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 24, 2020

Tolle Arbeit...nutze beide Widgets nebeneinander...ist es möglich das „Infektionen“ Widget linksbündig zu erstellen damit es von der Optik her besser zu dem „Inzidenz“ Widget passt...?
Welche Werte muss ich verändern bzw. ausgrauen...?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 24, 2020

@trigger64

  • Auskommentieren der Zeilen 205, 214, 221 und 238. (xyz.addSpacer())
  • In Zeile 235 true durch false ersetzen
    Dann sollte das Widget linksbündig angezeigt werden
@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 24, 2020

@marcelrebmann
Danke...perfekt..👍

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 24, 2020

@marcelrebmann

Sieht gut aus 😍 danke

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 24, 2020

Das einzigste was man noch überlegen könnte ist mehrere Landkreise auf ein Widget zu machen ... aber denke dies wird zu unübersichtlich und voll

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 24, 2020

@F3000
Mach Dir doch einfach einen Widgetstapel mit den verschiedenen Landkreisen...kannst Du dann einfach durchblättern...

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Oct 24, 2020

@trigger64 stimmt . Hab ich gar nicht dran gedacht 👍

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 25, 2020

27114593-80BA-474B-889F-525CF43D55DB

@marcelrebmann
Sollte bei einem „0“ Anstieg das Dreieck nicht nach rechts zeigen und „grau“ sein...?
...und das Dreieck beim Landkreis müsste eigentlich orange statt rot sein.
Kann es sein das die Trends erst nach ein oder zwei Tagen funktionieren...?
54EF933C-E9D7-4843-9AE4-E9C5C4F60073
Bei dem Infektionswidget funktioniert es...

@STJIKA

This comment has been minimized.

Copy link

@STJIKA STJIKA commented Oct 25, 2020

@trigger64: ..sieht cool aus das „Infektionen“ widget linksbündig......könntest du es mir zur Verfügung stellen..........?

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 25, 2020

@STJIKA
https://gist.github.com/marcelrebmann/64494e453deaf26cab3c14c9ff711e1e#gistcomment-3502650

Hat der Ersteller des Widgets hier beschrieben...ich weiß nicht ob ich das geänderte hier einfach so posten darf...

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 25, 2020

27114593-80BA-474B-889F-525CF43D55DB

@marcelrebmann
Sollte bei einem „0“ Anstieg das Dreieck nicht nach rechts zeigen und „grau“ sein...?
...und das Dreieck beim Landkreis müsste eigentlich orange statt rot sein.
Kann es sein das die Trends erst nach ein oder zwei Tagen funktionieren...?
54EF933C-E9D7-4843-9AE4-E9C5C4F60073
Bei dem Infektionswidget funktioniert es...

Die Trends für BL und Landkreis und DE berechnen sich aus den jeweiligen Inzidenzwerten der letzten 7 Tage, d.h. der Anstieg hängt nicht nur vom gestrigen Tag ab. Deshalb kann der Pfeil trotzdem nach oben zeigen und rot sein, obwohl heute keine neuen Infektionen dazugekommen sind.
Im Moment berechnen sich die Trends noch nicht aus der kompletten letzten Woche, da noch keine 7 Tage seit dem Release vergangen sind. Soll heißen: Die Pfeilrichtungen und Farben werden die Tage noch akkurater werden :)

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 25, 2020

Alles klar...danke...👍

@Majo1999

This comment has been minimized.

Copy link

@Majo1999 Majo1999 commented Oct 29, 2020

Hallo Marcel,
erstmal ein Kompliment an deine Arbeit und das du sie uns zur Verfügung stellst.
Ich habe folgendes Problem. Innerhalt von Gebäuden bekomme ich öfters einen Error, dass mein Standort zu ungenau ist. Kann man die Genauigkeit etwas herabsetzen? Aktuell liegt diese ja bei 3 Km, wenn ich das richtig gesehen habe. Da ich oft über Landkreise hinweg arbeite, habe ich den statischen Standort ausgestellt und gehe nach GPS.

Des weiteren nutze ich beide Widget-Funktionen von dir in zwei getrennten Widgets, also Landkreis und komplett Deutschland. Ich fände es schön, wenn es die Funktion gäbe, dass aus zwei 2x2 Widgets ein 2x4 Widget wird und man links den Kreis hat und rechts ganz Deutschland.

Falls das nicht von dir umgesetzt wird, trotzdem danke für deine jetzige Arbeit.

PS: ist es möglich die Schrift (Scriptable) unter dem Widget zu entfernen?

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Oct 30, 2020

@Majo1999
Danke und gerne doch.

Location
Generell ist es natürlich sicherer, wenn du den Standort fix in den Parametern eingibst. Bei der Abfrage des Standorts kann immer mal etwas nicht klappen.
Ich sehe hier zwei mögliche Wege:

  • Erste Lösung:
    Ich habe das Skript um ein Caching des Standortes erweitert -> Probiere das gerne mal.
    Wenn die Standortabfrage nicht klappt, dann wird die zuletzt bekannte Position genommen und angezeigt (falls vorhanden). Die Position wird lokal auf dem Gerät als Datei abgelegt und aktualisiert. (Wichtig: Die Standortfreigabe muss für Scriptable natürlich aktiviert sein)
    Ein blaues Standortsymbol oben rechts im Widget zeigt an, dass der gezeigte Standort aktuell ist. Das graue Symbol signalisiert, dass der gezeigte Standort der zuletzt gespeicherte ist.

  • Zweite Lösung:
    Wenn du mehrere fixe Standorte/Regionen hast, zwischen denen du dich bewegst, kannst du für jeden Standort ein Widget mit statischem Standort erstellen und diese dann in einem Widget-Stapel (Apple nennt das Smart-Stapel) zusammenfassen.

Medium (2x4) Widget
Das 2x4 große Widget ist tatsächlich schon in Planung. In den letzten Updates habe ich dazu den strukturellen Grundstein gelegt.

Schrift unter Widget
Soweit ich weiß, ist es nicht möglich, das "Scriptable" zu modifizieren. iOS nimmt (zumindest am iPhone) immer den Titel der App, die das Widget bereitstellt. Auf dem iPad (iPadOS) haben die Widgets keine Titel unten.

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 31, 2020

@trigger64

  • Auskommentieren der Zeilen 205, 214, 221 und 238. (xyz.addSpacer())
  • In Zeile 235 true durch false ersetzen
    Dann sollte das Widget linksbündig angezeigt werden

Moin,
kann es sein, dass die o.a. Zeilen nicht mehr stimmen? Welche Zeilen muss ich aktuell auskommentieren, wenn ich den Text linksbündig haben möchte?

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 31, 2020

@QWERTZ000
Ich hab Dir mal Screenshots angehängt...bei mir sind es die Zeilen 207,211,216,223 und 240...in Zeile 237 „true“ durch „false“ ersetzen...

C0528785-8A5E-44D9-A201-18DD215C3890
A7FEF1D1-C10B-4B40-B113-10AA1DA99E77
D68B05DF-749B-4C83-A8AA-87817E45FC1D

sieht bei mir dann aus wie auf dem mittleren Screenshot...

@QWERTZ000

This comment has been minimized.

Copy link

@QWERTZ000 QWERTZ000 commented Oct 31, 2020

@QWERTZ000
Ich hab Dir mal Screenshots angehängt...bei mir sind es die Zeilen 207,211,216,223 und 240...in Zeile 237 „true“ durch „false“ ersetzen...

C0528785-8A5E-44D9-A201-18DD215C3890
A7FEF1D1-C10B-4B40-B113-10AA1DA99E77
D68B05DF-749B-4C83-A8AA-87817E45FC1D

sieht bei mir dann aus wie auf dem mittleren Screenshot...

Danke für deine schnelle Antwort. Zwar sind es bei andere Zeilen (265, 269, 274, 281, 298 und 295 „true“ durch „false“ ersetzen) aber anhand der Screenschots habe ich es gefunden. Und es scheint zu funktionieren.

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Oct 31, 2020

👍

@kingmath

This comment has been minimized.

Copy link

@kingmath kingmath commented Nov 5, 2020

Kann man ggf. einen Parameter einfügen, welcher die INF Anzeige linksbündig setzt?

Tolle Arbeit! Vielen Dank 😊

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Nov 6, 2020

@kingmath stelle ich im nächsten Update bereit. Danke für dein Feedback 👍

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Nov 7, 2020

Update 07.11.2020

  • Das Infektionen (INF) Widget kann wahlweise zentriert oder linksbündig angezeigt werden.
    Einstellbar über die Konfigurations-Variable CONFIG. isInfectionsWidgetCentered
  • Die Hintergrundfarbe im Dark Mode ist jetzt nicht mehr komplett schwarz, sondern gleicht der anderer Apple-Widgets (beispielsweise dem Kalender-Widget)
  • Stadtkreise werden nun mit (SK) annotiert, um mehr Platz zu schaffen.

Infos und Screenshots, siehe erster Kommentar.

@trigger64

This comment has been minimized.

Copy link

@trigger64 trigger64 commented Nov 7, 2020

@marcelrebmann
Perfekt...danke für Deine Arbeit...👍

@kingmath

This comment has been minimized.

Copy link

@kingmath kingmath commented Nov 7, 2020

Vielen lieben Dank für deine tolle Arbeit!

Ein Vorschlag zur Variable „ isInfectionsWidgetCentered“. Eine Abfrage in Scriptable ob INF oder INFleft genutzt wird. INFleft bewirkt isInfectionsWidgetCentered false. Dies hätte den Charm, dass man bei einem Update den Quellcode nur kopieren und nicht editieren muss. Die Einstellungen kommen dann nur über den Parameter. Nur ein Vorschlag für ein Update. Tolle Arbeit!

@cl4udiu5

This comment has been minimized.

Copy link

@cl4udiu5 cl4udiu5 commented Nov 9, 2020

@marcelrebmann
Danke für die tolle Arbeit. Wirklich ein cooles Widget.
Mir würde eine Erweiterung noch gut gefallen.
Und zwar die Neuinfektionen des Bundeslandes, welches ja sowieso schon angezeigt wird.
Vielleicht findest du da ja noch etwas Platz im Widget.

SK wird ja auch schon angezeigt (z.B. bei Stuttgart). Schön wäre auch noch LK für Landkreis (z.B. Neu-Ulm).

@Rehner

This comment has been minimized.

Copy link

@Rehner Rehner commented Nov 14, 2020

Sorry für die wahrscheinlich blöde Frage, aber wo und wie gebe ich dem Script denn den Parameter inf mit um die Infektionszahlen gezeigt zu bekommen?

Edith sagt: Wer schaut der findet. Habe es rausgefunden.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Dec 8, 2020

Update 08.12.2020

Ein kleines Update aus gegebenen Anlass:

  • Neue Farbe (dunkles Magenta) bei Inzidenzen über dem 200er Grenzwert.
  • Die Medium-Größe des Scriptable Widgets wird nun auch unterstützt.
    IMG_5A63D940C0D6-1
@cl4udiu5

This comment has been minimized.

Copy link

@cl4udiu5 cl4udiu5 commented Dec 8, 2020

B7331B9F-4EF4-45F6-96BA-E7F27DD7F85B

Update 08.12.2020

Ein kleines Update aus gegebenen Anlass:

  • Neue Farbe (dunkles Magenta) bei Inzidenzen über dem 200er Grenzwert.
  • Die Medium-Größe des Scriptable Widgets wird nun auch unterstützt.
    IMG_5A63D940C0D6-1

Danke für das Update.
Ich nutze vorallem den INF Parameter.
Bekomme aber eine Fehlermeldung, wenn ich das Update einspiele.

Edit:
Kann es sein, dass der INF Parameter nur noch in einem Small Widget geht?
Wäre super, wenn das im Medium Widget auch gehen würde wie bisher.
Also nur die Infektionen für DE zentriert anzeigen.

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Dec 8, 2020

@cl4udiu5 An die Möglichkeit mit Medium-Widget + nur Infektionszahlen hatte ich tatsächlich nicht gedacht. Das sollte nun auch wieder möglich sein, habe den Code entsprechend angepasst. Danke für den Hinweis!

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Dec 28, 2020

Update 28.12.2020

Behebt ein Problem, bei dem gelegentlich (oftmals morgens) keine Daten angezeigt wurden - vermutlich aufgrund starker Auslastung der RKI API.

  • Caching der zuletzt abgefragten Daten lokal auf dem Gerät. Falls keine Daten geladen werden können, werden diese angezeigt.
  • Verbesserung der Effizienz durch weniger Aktualisierungen im Hintergrund.
@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Dec 28, 2020

Hi @marcelrebmann

wäre es möglich in Zukunft auch die Impfquoten anzuzeigen ?
Diese sind seit heute verfügbar.

https://www.rki.de/DE/Content/Infekt/Impfen/Impfstatus/impfstatus_node.html

@F3000

This comment has been minimized.

Copy link

@F3000 F3000 commented Dec 29, 2020

Hier gibt es schon ein Beispiel Skript dazu 👍

https://gist.github.com/marco79cgn/b5f291d6242a2c530e56c748f1ae7f2c

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Jan 11, 2021

Update 11.01.2021

Impfquoten für Bundesländer und Deutschland werden angezeigt (Datenquelle: RKI, in der Regel werktäglich aktualisiert).

  • Prozentuale Anzeige der Impfungen im jeweiligen Bundesland bzw. in Deutschland (INF-Modus)
  • Zunahme im Vergleich zum Vortag
  • Indikator (Ausrufezeichen mit Pfeil) zur Info, falls nur "veraltete" Impfdaten zur Verfügung stehen (Die Daten werden vom RKI nur werktags aktualisiert).

IMG_9D54F3D9D555-1 IMG_5DF9BB37DC0A-1
IMG_0324

@marcelrebmann

This comment has been minimized.

Copy link
Owner Author

@marcelrebmann marcelrebmann commented Jan 11, 2021

WICHTIG: MIGRATION ZU GITHUB REPO
Zur besseren Verwaltung habe ich das Skript in ein GitHub-Repository umgezogen: https://github.com/marcelrebmann/corona-widget-ios. Zukünftige Updates und alles andere werden ab nun dort bereitgestellt! 🙃

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