├── ImpfQuoten.js
├── LICENSE
├── README.md
└── img
├── error.png
├── pic1.png
├── pic2.png
├── pic3.png
├── pic4.png
├── pic5.png
├── pic6.png
├── widget1.png
└── widget2.png
/ImpfQuoten.js:
--------------------------------------------------------------------------------
1 | // Variables used by Scriptable.
2 | // These must be at the very top of the file. Do not edit.
3 | // icon-color: deep-green; icon-glyph: syringe;
4 | //
5 | // Script für https://scriptable.app
6 | // iOS Widget zur Anzeige der gegen COVID-19 geimpften Personenzahl.
7 | // Die Quote der Geimpften mit Bezug auf die Bevölkerung von Deutschland oder eines gewählten Bundeslands.
8 | // Zusätzlich werden die Zahlen mit einem Fortschrittsbalken visualisiert.
9 | // Konfiguriert als Widget Medium. Schaltet automatisch auch in den DarkMode.
10 | //
11 | // Script by MacSchierer, 03.05.2022, v2.3
12 | // Download der aktuellen Version hier: GitHub https://github.com/MacSchierer/ImpfQuote
13 | // https://fckaf.de/Bn0
14 | //
15 | // Verwendet die bereitgestellte Robert Koch-Institut COVID-19 API - von Marlon Lückert
16 | // https://api.corona-zahlen.org, https://github.com/marlon360/rki-covid-api
17 |
18 | //
19 | // Optionale Konfiguration
20 | //
21 | // Individuelle Farbstufen für die Impfquote:
22 | // Rot = Step1st < 25, Grün = Step2nd > 85, Dazwischen Orange, Ziel > 85 = "Herdenimmunität"
23 | const Step1st = 25
24 | const Step2nd = 85
25 | const StepFin = 100
26 |
27 | debug = false
28 |
29 | //
30 | // Ab hier nichts ändern
31 | //
32 | let APIurl = "https://api.corona-zahlen.org/vaccinations"
33 | let hasError = false
34 | let ErrorTxt = ""
35 | let RegionKey= "Deutschland"
36 |
37 | const BarWidth = 15
38 | const BarHeigth = 105
39 |
40 | let param = args.widgetParameter // Abfrage des Parameters vom Widget
41 | if (debug) {param = "de"}
42 | if (param != null && param.length > 0) {
43 | param = param.toUpperCase()
44 | if (setRegionKey(param) != false) {
45 | RegionKey = setRegionKey(param)
46 | RegionKey = param
47 | }
48 | else {
49 | hasError = true
50 | ErrorTxt += "Bundesland konnte nicht zugeordnet werden.\r\rBitte überprüfe den Parameter im Widget."
51 | }
52 | }
53 |
54 | try {
55 | AllItems = await loadItems(APIurl)
56 | } catch (e) {
57 | hasError = true
58 | ErrorTxt += "Das Widget konnte keine Daten abrufen."
59 | }
60 |
61 | try {
62 | if (RegionKey != "DE") {
63 | RegItems = AllItems.data.states[RegionKey]
64 | RegionName = RegItems.name
65 | } else {
66 | RegItems = AllItems.data
67 | RegionName = "Deutschland"
68 | }
69 |
70 | // Daten zuordnen
71 | Vacc1st = RegItems.vaccinated
72 | QuoteVacc1st = RegItems.quote*100
73 | DeltaVacc1st = RegItems.delta
74 | Vacc2nd = RegItems.secondVaccination.vaccinated
75 | QuoteVacc2nd = RegItems.secondVaccination.quote*100
76 | DeltaVacc2nd = RegItems.secondVaccination.delta
77 | Booster1st = RegItems.boosterVaccination.vaccinated
78 | QuoteBooster1st = RegItems.boosterVaccination.quote*100
79 | DeltaBooster1st = RegItems.boosterVaccination.delta
80 | Booster2nd = RegItems['2ndBoosterVaccination'].vaccinated
81 | QuoteBooster2nd = RegItems['2ndBoosterVaccination'].quote*100
82 | DeltaBooster2nd = RegItems['2ndBoosterVaccination'].delta
83 |
84 | if(debug){
85 | log("Region: " + RegionName)
86 | log("Vacc1st: " + Vacc1st + ", " + QuoteVacc1st + ", " + DeltaVacc1st)
87 | log("Vacc2nd: " + Vacc2nd + ", " + QuoteVacc2nd + ", " + DeltaVacc2nd)
88 | log("Booster1st: " + Booster1st + ", " + QuoteBooster1st + ", " + DeltaBooster1st)
89 | log("Booster2nd: " + Booster2nd + ", " + QuoteBooster2nd + ", " + DeltaBooster2nd)
90 | log("Stand: " + AllItems.meta.lastCheckedForUpdate)
91 | }
92 |
93 | } catch (e) {
94 | hasError = true
95 | ErrorTxt += "Beim Verarbeiten der Daten ist ein Fehler aufgetreten.\r\r"
96 | ErrorTxt += "API: " + AllItems.message
97 | }
98 |
99 | // Fraben definieren
100 | WidgetBgColor = Color.dynamic(new Color("#fefefe"), new Color("#1e1e1e"))
101 | ContentBGColor = Color.dynamic(new Color("#efefef"), new Color("#444444"))
102 | MainTextColor = Color.dynamic(new Color("#000000"), new Color("#ffffff"))
103 | SubTextColor = Color.dynamic(new Color("#666666"), new Color("#aaaaaa"))
104 | TitelColor = MainTextColor
105 | BarTextColor1 = Color.dynamic(new Color("#ffffff"), new Color("#000000"))
106 | BarTextColor2 = Color.dynamic(new Color("#000000"), new Color("#ffffff"))
107 |
108 | // Ausgabe aufgelaufene Fehler oder Widget
109 | if (hasError == true) {
110 | let widget = errorWidget(ErrorTxt)
111 | Script.setWidget(widget)
112 | widget.presentMedium()
113 | Script.complete()
114 | } else {
115 |
116 | const widget = new ListWidget()
117 | widget.backgroundColor = WidgetBgColor
118 | widget.setPadding(15, 15, 15, 15)
119 | const Title = widget.addStack()
120 | let TitleText = Title.addText("COVID-19 Impfungen")
121 | TitleText.textColor = TitelColor
122 | TitleText.font = Font.boldSystemFont(12)
123 | TitleText.minimumScaleFactor = 0.5
124 | TitleText.lineLimit = 1
125 | Title.addSpacer()
126 | widget.borderWidth = 1
127 | widget.borderColor = MainTextColor
128 | let DateText = Title.addDate(new Date(AllItems.meta.lastCheckedForUpdate))
129 | DateText.textColor = SubTextColor
130 | DateText.applyDateStyle()
131 | DateText.font = Font.boldSystemFont(8)
132 | const SubTitle = widget.addStack()
133 | let SubTitleText = SubTitle.addText(RegionName)
134 | SubTitleText.font = Font.systemFont(10)
135 | SubTitleText.textColor = SubTextColor
136 | SubTitleText.lineLimit = 1
137 | widget.addSpacer(2)
138 |
139 | const Content = widget.addStack()
140 | Content.setPadding(2,2,2,2)
141 | Content.layoutHorizontally()
142 |
143 | const Stack1 = Content.addStack()
144 | Stack1.layoutVertically()
145 | Stack1.backgroundColor = ContentBGColor
146 | Stack1.cornerRadius = 4
147 | Stack1.setPadding(4,4,4,4)
148 | const Stack1Head = Stack1.addStack()
149 | Stack1Head.addSpacer()
150 | let Title1stText = Stack1Head.addText("Vollständig")
151 | Title1stText.textColor = MainTextColor
152 | Title1stText.font = Font.boldSystemFont(14)
153 | Stack1Head.addSpacer()
154 | Stack1.addSpacer(4)
155 | const Stack1Vacc = Stack1.addStack()
156 | Stack1Vacc.addSpacer()
157 | let VaccFullText = Stack1Vacc.addText(Vacc2nd.toLocaleString('de-DE'))
158 | VaccFullText.textColor = MainTextColor
159 | VaccFullText.font = Font.boldSystemFont(14)
160 | Stack1Vacc.addSpacer()
161 | const Stack1Diff = Stack1.addStack()
162 | Stack1Diff.addSpacer()
163 | let DiffFullText = Stack1Diff.addText("+" + DeltaVacc2nd.toLocaleString('de-DE'))
164 | DiffFullText.textColor = SubTextColor
165 | DiffFullText.font = Font.systemFont(12)
166 | Stack1Diff.addSpacer()
167 | Stack1.addSpacer(4)
168 | const Stack1Percent = Stack1.addStack()
169 | Stack1Percent.layoutHorizontally()
170 | Stack1Percent.centerAlignContent()
171 | Stack1Percent.addSpacer()
172 | let QuoteFullText = Stack1Percent.addText((QuoteVacc2nd.toLocaleString('de-DE')).replace('.', ','))
173 | QuoteFullText.textColor = MainTextColor
174 | QuoteFullText.font = Font.boldSystemFont(28)
175 | QuoteFullEin = Stack1Percent.addText("%")
176 | QuoteFullEin.textColor = SubTextColor
177 | QuoteFullEin.font = Font.systemFont(14)
178 | Stack1Percent.addSpacer()
179 | Stack1.addSpacer()
180 | Content.addSpacer()
181 | const BarContent1 = Content.addStack()
182 | BarContent1.layoutVertically()
183 | const progressBar1st = BarContent1.addImage(creatProgress(QuoteVacc2nd, QuoteVacc1st))
184 | progressBar1st.cornerRadius = 4
185 | progressBar1st.imageSize = new Size(BarWidth, BarHeigth)
186 |
187 | Content.addSpacer()
188 |
189 | const BarContent2 = Content.addStack()
190 | BarContent2.layoutVertically()
191 | const progressBar2nd = BarContent2.addImage(creatProgress(QuoteBooster1st, QuoteBooster2nd))
192 | progressBar2nd.cornerRadius = 4
193 | progressBar2nd.imageSize = new Size(BarWidth, BarHeigth)
194 | Content.addSpacer()
195 | const Stack2 = Content.addStack()
196 | Stack2.layoutVertically()
197 | Stack2.backgroundColor = ContentBGColor
198 | Stack2.cornerRadius = 4
199 | Stack2.setPadding(4,4,4,4)
200 | const Stack2Head = Stack2.addStack()
201 | Stack2Head.addSpacer()
202 | let Title2ndText = Stack2Head.addText("Auffrischung")
203 | Title2ndText.textColor = MainTextColor
204 | Title2ndText.font = Font.boldSystemFont(14)
205 | Stack2Head.addSpacer()
206 | Stack2.addSpacer(4)
207 | const Stack2Vacc = Stack2.addStack()
208 | Stack2Vacc.addSpacer()
209 | let VaccBoosterText = Stack2Vacc.addText(Booster1st.toLocaleString('de-DE'))
210 | VaccBoosterText.textColor = MainTextColor
211 | VaccBoosterText.font = Font.boldSystemFont(14)
212 | Stack2Vacc.addSpacer()
213 | const Stack2Diff = Stack2.addStack()
214 | Stack2Diff.addSpacer()
215 | let DiffBoosterText = Stack2Diff.addText("+" + DeltaBooster1st.toLocaleString('de-DE'))
216 | DiffBoosterText.textColor = SubTextColor
217 | DiffBoosterText.font = Font.systemFont(12)
218 | Stack2Diff.addSpacer()
219 | Stack2.addSpacer(4)
220 | const Stack2Percent = Stack2.addStack()
221 | Stack2Percent.layoutHorizontally()
222 | Stack2Percent.centerAlignContent()
223 | Stack2Percent.addSpacer()
224 | let QuoteBoosterText = Stack2Percent.addText((QuoteBooster1st.toLocaleString('de-DE')).replace('.', ','))
225 | QuoteBoosterText.textColor = MainTextColor
226 | QuoteBoosterText.font = Font.boldSystemFont(28)
227 | QuoteBoosterEin = Stack2Percent.addText("%")
228 | QuoteBoosterEin.textColor = SubTextColor
229 | QuoteBoosterEin.font = Font.systemFont(14)
230 | Stack2Percent.addSpacer()
231 | Stack2.addSpacer()
232 |
233 | // Ausgabe
234 | if (!config.runsInWidget) {
235 | await widget.presentMedium()
236 | } else {
237 | Script.setWidget(widget)
238 | }
239 | Script.complete()
240 | }
241 |
242 | //
243 | // Error Widget
244 | //
245 | function errorWidget(reason){
246 | let w = new ListWidget()
247 | w.setPadding(5,5,5,5)
248 | let myGradient = new LinearGradient()
249 | w.backgroundColor = new Color("#933")
250 | myGradient.colors = [new Color("#990000"), new Color("#ff0000")]
251 | myGradient.locations = [0.0,1]
252 | w.backgroundGradient = myGradient
253 | let title = w.addText("Fehler")
254 | title.centerAlignText()
255 | title.textColor = Color.white()
256 | title.font = Font.semiboldSystemFont(24)
257 | title.minimumScaleFactor = 0.5
258 | let reasonText = w.addText(reason)
259 | reasonText.centerAlignText()
260 | reasonText.textColor = Color.white()
261 | reasonText.font = Font.semiboldSystemFont(12)
262 | reasonText.minimumScaleFactor = 0.5
263 | return w
264 | }
265 |
266 | //
267 | // JSON holen
268 | //
269 | async function loadItems(APIurl) {
270 | let req = new Request(APIurl)
271 | let json = await req.loadJSON()
272 | return json
273 | }
274 |
275 | function creatProgress(BarValue1, BarValue2) {
276 | BarValue1 = Math.round(BarValue1)
277 | BarValue2 = Math.round(BarValue2)
278 | const context = new DrawContext()
279 | context.size = new Size(BarWidth, BarHeigth)
280 | context.opaque = false
281 | context.respectScreenScale = true
282 | // BG
283 | const path = new Path()
284 | path.addRoundedRect(new Rect(0, 0, BarWidth, BarHeigth),4,4)
285 | context.addPath(path)
286 | context.setFillColor(ContentBGColor)
287 | context.fillPath()
288 | // BarValue1
289 | if (BarValue1 < Step1st) {BarColor1 = new Color("#bb1e10")}
290 | if (BarValue2 < Step1st) {BarColor2 = new Color("#bb1e1075")}
291 |
292 | if (BarValue1 >= Step1st && BarValue1 < Step2nd) {BarColor1 = new Color("#f7b500")}
293 | else if (BarValue1 >= Step2nd) {BarColor1 = new Color("#00b347")}
294 |
295 | if (BarValue2 >= Step1st && BarValue2 < Step2nd) {BarColor2 = new Color("#f7b50075")}
296 | else if (BarValue2 >= Step2nd) {BarColor2 = new Color("#00b34775")}
297 |
298 | // BarValue2
299 | context.setFillColor(BarColor2)
300 | const path2 = new Path()
301 | const path2BarHeigth = (BarHeigth * (BarValue2 / StepFin) > BarHeigth) ? BarHeigth : BarHeigth * (BarValue2 / StepFin)
302 | path2.addRoundedRect(new Rect(0, BarHeigth, BarWidth, -path2BarHeigth),2,2)
303 | context.addPath(path2)
304 | context.fillPath()
305 |
306 | // BarValue1
307 | context.setFillColor(BarColor1)
308 | const path1 = new Path()
309 | const path1BarHeigth = (BarHeigth * (BarValue1 / StepFin) > BarHeigth) ? BarHeigth : BarHeigth * (BarValue1 / StepFin)
310 | path1.addRoundedRect(new Rect(0, BarHeigth, BarWidth, -path1BarHeigth),2,2)
311 | context.addPath(path1)
312 | context.fillPath()
313 |
314 | context.setFont(Font.boldSystemFont(8))
315 | context.setTextAlignedCenter()
316 | if (BarValue1 < 90) {
317 | context.setTextColor(SubTextColor)
318 | context.drawTextInRect("%", new Rect(0, 3, BarWidth, BarHeigth))
319 | } else {
320 | context.setTextColor(BarTextColor1)
321 | context.drawTextInRect("%", new Rect(0, BarHeigth-15, BarWidth, BarHeigth))
322 | }
323 | if (BarValue1 < 10) {
324 | PosCorr = -10
325 | context.setTextColor(BarTextColor2)
326 | }
327 | else {
328 | PosCorr = 2
329 | context.setTextColor(BarTextColor1)
330 | }
331 | context.drawTextInRect(BarValue1.toString(), new Rect(0, BarHeigth-path1BarHeigth+PosCorr, BarWidth, path1BarHeigth-PosCorr))
332 | return context.getImage()
333 | }
334 |
335 | //
336 | // Regionen und Widgetparameter
337 | //
338 | function setRegionKey(Region) {
339 | let Regions = { BW: "Baden-Württemberg", BY: "Bayern", BE: "Berlin", BB: "Brandenburg", HB: "Bremen", HH: "Hamburg", HE: "Hessen", MV: "Mecklenburg-Vorpommern", NI: "Niedersachsen", NW: "Nordrhein-Westfalen", RP: "Rheinland-Pfalz", SL: "Saarland", SN: "Sachsen", ST: "Sachsen-Anhalt", SH: "Schleswig-Holstein", TH: "Thüringen", DE: "Deutschland" };
340 | if (Regions.hasOwnProperty(Region)) {
341 | result = Regions[Region]
342 | } else {
343 | result = false
344 | }
345 | return result
346 | }
347 |
348 |
349 | // End of Script
350 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 MacSchierer
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ImpfQuoten, Ein Scriptable Widget
2 | Ein Scriptable Widget zur Anzeige der gegen COVID-19 geimpften Personenzahl.
3 | Die Quote der Geimpften mit Bezug auf die Bevölkerung von Deutschland oder eines gewählten Bundeslands.
4 | Zusätzlich werden die Zahlen mit einem Fortschrittsbalken visualisiert.
5 |

6 | Zahlen zu vollständig Geimpften und Auffrischimpfungen (Booster):
7 | - Anzahl der Geimpften
8 | - Differenz zum Vortag
9 | - Prozentsatz mit Bezug auf die Bevölkerung
10 |
11 | ## Verwendung
12 |
13 | * Download Scriptable App für iOS Geräte - https://scriptable.app
14 | * Download/Import der ImpfQuoten.js Datei nach iCloud/Scriptable
15 | * Auf dem Homescreen ein neues mittleres Scriptable Widget erstellen - Parameter für Bundesland optional
16 |

17 | Das Skript ist aktuell für die mittlere Widgetgröße ausgelegt und wurde auf einem iPhone 12Pro, Xs getestet.
18 | Auf anderen Geräten oder Widgetgrößen kann es ggf. zu Abweichungen in der Darstellung kommen.
19 |
20 | ## Features
21 |
22 | * Quelle der Daten: Robert Koch-Institut COVID-19 API - von Marlon Lückert >> https://api.corona-zahlen.org
23 | * Über den Parameter des Widgets kann ein Bundesland vorgegben werden. Kürzel nach ISO 3166-2:DE
24 | * Wechselt gemäß der Geräteeinstellung automatisch in den Darkmode
25 | * Individuelle Farbstufen für die Impfquote: Rot = Step1st < 25, Grün = Step2nd > 85, Dazwischen Orange, Ziel > 85 = "Herdenimmunität"
26 |
27 | ## Kürzel für den Parameter des Widgets
28 | BW = Baden-Württemberg
29 | BY = Bayern
30 | BE = Berlin
31 | BB = Brandenburg
32 | HB = Bremen
33 | HH = Hamburg
34 | HE = Hessen
35 | MV = Mecklenburg-Vorpommern
36 | NI = Niedersachsen
37 | NW = Nordrhein-Westfalen
38 | RP = Rheinland-Pfalz
39 | SL = Saarland
40 | SN = Sachsen
41 | ST = Sachsen-Anhalt
42 | SH = Schleswig-Holstein
43 | TH = Thüringen
44 | DE = Deutschland
45 |
46 |
47 | ## Beispiele
48 |

49 |

50 | ## Bekannte Probleme
51 |
52 | * Fortschrittsbalken wechselt nicht direkt in das zugehörige Erscheinungsbild (hell/dunkel)
53 | * Tritt ein Fehler beim Datenabruf auf, wird eine Fehlermeldung angezeigt:
54 | 
55 |
56 | ## Changelog
57 | * v2.3 Neue API >> Robert Koch-Institut COVID-19 API - von Marlon Lückert
58 | * v2.1 Fix %-Zeichen, Erstimpfungen werden im linken Fortschirttsbalken schattiert im Hintergrund dargestellt
59 | * v2.0 Anzeige: Impfquote vollständig geimpft, Impfquote Auffrischimpfung
60 | * v1.3 Impfquoten angepasst, API V2 - https://github.com/ThisIsBenny/rki-vaccination-data
61 | * v1.2 Kleine Korrekturen: Farben, Dezimaltrenner
62 | * v1.1 Anzeige der Erstimpfungen als kleines Widget
63 | * v1.0 Release GitHub
64 |
65 | ## Hinweis zur Quelle und Datenstand
66 | Verwendet die bereitgestellte Robert Koch-Institut COVID-19 API - von Marlon Lückert
67 | https://api.corona-zahlen.org, https://github.com/marlon360/rki-covid-api
68 |
--------------------------------------------------------------------------------
/img/error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/error.png
--------------------------------------------------------------------------------
/img/pic1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic1.png
--------------------------------------------------------------------------------
/img/pic2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic2.png
--------------------------------------------------------------------------------
/img/pic3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic3.png
--------------------------------------------------------------------------------
/img/pic4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic4.png
--------------------------------------------------------------------------------
/img/pic5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic5.png
--------------------------------------------------------------------------------
/img/pic6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/pic6.png
--------------------------------------------------------------------------------
/img/widget1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/widget1.png
--------------------------------------------------------------------------------
/img/widget2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MacSchierer/ImpfQuoten/fcdd3ea7df7c66a13453a50a6bdd81db5b8b0ca7/img/widget2.png
--------------------------------------------------------------------------------