Skip to content

Instantly share code, notes, and snippets.

@marco79cgn
Last active January 11, 2023 21:47
Star You must be signed in to star a gist
Save marco79cgn/b5f291d6242a2c530e56c748f1ae7f2c to your computer and use it in GitHub Desktop.
A Scriptable widget that shows the amount of people who have received the corona vaccination in Germany
// 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
//
@rafaelmaeuer
Copy link

Variante 1 funktionierte leider nicht unter macOS, Variante 2 dafür schon - gefällt mir gut: habe ich in v1.4.3 übernommen

@thorstenleidl
Copy link

Danke @rafaelmaeuer, habe dank deinem tsv parsing meinen fork wiederbeleben können 👍🏻

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