A Scriptable widget that shows the amount of people who have received the corona vaccination in Germany

May 6, 2022 · View on GitHub

// Version 1.3.0 // 27.11.2021 // // Variables used by Scriptable. // These must be at the very top of the file. Do not edit. // icon-color: red; icon-glyph: notes-medical; // Mit Caching und Fallback const cacheMinutes = 60; // 60 min const today = new Date(); const neededTotalVaccinations = 83200000; let result; let resultDe; let width = 100; const h = 5;

const colorLightGreen = new Color("#47b881") const colorDarkGreen = new Color("#00783e")

let widget = new ListWidget(); widget.setPadding(6, 12, 8, 12); widget.url = "https://interaktiv.morgenpost.de/corona-impfungen-deutschland-bundeslaender-weltweit/";

await getNumbers(); await createWidget(); Script.setWidget(widget); Script.complete();

if (config.runsInApp) { widget.presentSmall(); }

async function createWidget() {

widget.addSpacer();

const amountFirstPerCent = resultDe.vaccinations1_quota;
const amountSecondPerCent = resultDe.vaccinations2_quota;
const amountBoosterPerCent = resultDe.vaccinations3_quota;

let firstDoseStack = widget.addStack()
firstDoseStack.layoutHorizontally()
let amountFirstText = firstDoseStack.addText("Erstimpfung");
amountFirstText.font = Font.boldSystemFont(12);
firstDoseStack.addSpacer()
let percentFirstText = firstDoseStack.addText(amountFirstPerCent.toLocaleString() + "%")
percentFirstText.font = Font.boldSystemFont(12);

widget.addSpacer(2);

let progressStack = widget.addStack();
progressStack.layoutVertically();
let progressNumberStack = widget.addStack();
progressNumberStack.layoutHorizontally();

const progressText = progressNumberStack.addText((resultDe.vaccinations1).toLocaleString());
progressText.font = Font.mediumSystemFont(10);
progressStack.addImage(createProgress((resultDe.vaccinations1), colorLightGreen));

widget.addSpacer(3)

let secondDoseStack = widget.addStack()
secondDoseStack.layoutHorizontally()
let amountSecondText = secondDoseStack.addText("Vollständig");
amountSecondText.font = Font.boldSystemFont(12);
secondDoseStack.addSpacer()
let percentSecondText = secondDoseStack.addText(amountSecondPerCent.toLocaleString() + "%")
percentSecondText.font = Font.boldSystemFont(12);

widget.addSpacer(2)

let progressStack2 = widget.addStack();
progressStack2.layoutVertically();
let progressNumberStack2 = widget.addStack();
progressNumberStack2.layoutHorizontally();

const progressText2 = progressNumberStack2.addText(resultDe.vaccinations2.toLocaleString());
progressText2.font = Font.mediumSystemFont(10);
progressStack2.addImage(createProgress(resultDe.vaccinations2, colorLightGreen));

widget.addSpacer(3);

let boosterStack = widget.addStack()
boosterStack.layoutHorizontally()
let amountBoosterText = boosterStack.addText("Booster");
amountBoosterText.font = Font.boldSystemFont(12);
boosterStack.addSpacer()
let percentBoosterText = boosterStack.addText(amountBoosterPerCent.toLocaleString() + "%")
percentBoosterText.font = Font.boldSystemFont(12);

widget.addSpacer(2)

let progressStack3 = widget.addStack();
progressStack3.layoutVertically();
let progressNumberStack3 = widget.addStack();
progressNumberStack3.layoutHorizontally();

const progressText3 = progressNumberStack3.addText(resultDe.vaccinations3.toLocaleString());
progressText3.font = Font.mediumSystemFont(10);
progressStack3.addImage(createProgress(resultDe.vaccinations3, colorLightGreen));

widget.addSpacer(6)

let calendarStack = widget.addStack();
const lastUpdateDate = new Date(resultDe.date);
let description = widget.addText("Stand: " + lastUpdateDate.toLocaleDateString());
description.centerAlignText();
description.font = Font.mediumSystemFont(9);

//   widget.addSpacer(8)

}

// get images from local storage or download them once async function getImage(image) { let fm = FileManager.local(); let dir = fm.documentsDirectory(); let path = fm.joinPath(dir, image); if (fm.fileExists(path)) { return fm.readImage(path); } else { // download once let imageUrl; switch (image) { case "vac-logo.png": imageUrl = "https://i.imgur.com/ZsBNT8E.png"; break; case "calendar-icon.png": imageUrl = "https://i.imgur.com/Qp8CEFf.png"; break; default: console.log(Sorry, couldn't find ${image}.); } let req = new Request(imageUrl); let loadedImage = await req.loadImage(); fm.writeImage(path, loadedImage); return loadedImage; } }

async function getNumbers() { // Set up the file manager. const files = FileManager.local();

// Set up cache
const cachePath = files.joinPath(
    files.cacheDirectory(),
    "api-cache-covid-vaccination-numbers-mopo"
);
const cacheExists = files.fileExists(cachePath);
const cacheDate = cacheExists ? files.modificationDate(cachePath) : 0;

// Get Data
try {
    // If cache exists and it's been less than 60 minutes since last request, use cached data.
    if (
        cacheExists &&
        today.getTime() - cacheDate.getTime() < cacheMinutes * 60 * 1000
    ) {
        console.log("Get from Cache");
        result = JSON.parse(files.readString(cachePath));
    } else {
        console.log("Get from API");
        const req2 = new Request(
            "https://interaktiv.morgenpost.de/data/corona/rki-vaccination-latest.json"
        );
        result = await req2.loadJSON();
        console.log("Write Data to Cache");
        try {
            files.writeString(cachePath, JSON.stringify(result));
        } catch (e) {
            console.log("Creating Cache failed!");
            console.log(e);
        }
    }
} catch (e) {
    console.error(e);
    if (cacheExists) {
        console.log("Get from Cache");
        result = JSON.parse(files.readString(cachePath));
    } else {
        console.log("No fallback to cache possible. Due to missing cache.");
    }
}
await setTotalVacNoForGermany(result);

}

async function setTotalVacNoForGermany(result) { for (var i = result.length - 1; i >= 0; i--) { let currentItem = result[i]; if (currentItem["id"] === "de") { resultDe = currentItem; } } }

function createProgress(vacNo, color) { const context = new DrawContext(); context.size = new Size(width, h); context.opaque = false; context.respectScreenScale = true; context.setFillColor(new Color("#d2d2d7")); const path = new Path(); path.addRoundedRect(new Rect(0, 0, width, h), 3, 2); context.addPath(path); context.fillPath(); context.setFillColor(color); const path1 = new Path(); const path1width = (width * vacNo) / neededTotalVaccinations > width ? width : (width * vacNo) / neededTotalVaccinations; path1.addRoundedRect(new Rect(0, 0, path1width, h), 3, 2); context.addPath(path1); context.fillPath();

return context.getImage();

}

// // Bitte bis zum Ende kopieren //