Hi everyone,
I was happy to find this forum and learnt a lot from it with regards to the Scriptable app.
Just wanted to share the widget that I created showing the covid-19 data for Belgium, taking in figures directly from the CSV that is shared on the government website. (Scienscano)
This is the result…
For those interested in the code… Here is it is (could be done a lot better and probably needs refactoring! Also a lot of improvements can be done. Any feedback on the widget or the code is welcome! I`m rather new to programming)
// Variables used by Scriptable.
// These must be at the very top of the file. Do not edit.
// icon-color: light-brown; icon-glyph: magic;
// Icons made by https://www.flaticon.com/authors/freepik Freepik
// from Flaticon
const url = 'https://epistat.sciensano.be/Data/COVID19BE_HOSP.csv';
const urlCases = 'https://epistat.sciensano.be/Data/COVID19BE_tests.csv';
const urlDeaths = 'https://epistat.sciensano.be/Data/COVID19BE_MORT.csv';
async function loadText(url) {
let req = new Request(url)
let txt = await req.loadString()
return txt;
}
async function getHosp() {
let data = await loadText(url);
const rows = data.split('\n').slice(1);
dates = [];
newIns = [];
newOuts = [];
totalIns = [];
let previousDate = '2020-03-15';
let newInTotal = 0;
let newOutTotal = 0;
let totalInTotal = 0;
rows.forEach(row => {
const cols = row.split(",");
const date = cols[0];
const newInCurrentLine = parseInt(cols[8]);
const newOutCurrentLine = parseInt(cols[9]);
const totalInCurrentLine = parseInt(cols[4]);
if (previousDate === date) {
dates.pop();
newIns.pop();
newOuts.pop();
totalIns.pop();
newInTotal += newInCurrentLine;
newOutTotal += newOutCurrentLine;
totalInTotal += totalInCurrentLine;
} else {
newInTotal = newInCurrentLine;
newOutTotal = newOutCurrentLine;
totalInTotal = totalInCurrentLine;
previousDate = date;
}
dates.push(date);
newIns.push(newInTotal);
newOuts.push(newOutTotal);
totalIns.push(totalInTotal);
});
let netResult = [];
for (let i = 0; i < newIns.length ; i++) {
let difference = newIns[i] - newOuts[i];
netResult.push(difference);
}
return { dates, newIns, newOuts, netResult, totalIns };
}
async function getCases() {
let data = await loadText(urlCases);
const rows = data.split('\n').slice(1);
dates = [];
tests = [];
positives = [];
let previousDate = '2020-03-15';
let testsTotal = 0;
let positivesTotal = 0;
rows.forEach(row => {
const cols = row.split(",");
const date = cols[0];
const testsCurrentLine = parseInt(cols[3]);
const positivesCurrentLine = parseInt(cols[4]);
if (previousDate === date) {
dates.pop();
tests.pop();
positives.pop();
testsTotal += testsCurrentLine;
positivesTotal += positivesCurrentLine;
} else {
testsTotal = testsCurrentLine;
positivesTotal = positivesCurrentLine;
previousDate = date;
}
dates.push(date);
tests.push(testsTotal);
positives.push(positivesTotal);
});
return { dates, tests, positives};
}
async function getDeaths() {
let data = await loadText(urlDeaths);
const rows = data.split('\n').slice(1);
dates = [];
deaths = [];
let previousDate = '2020-03-15';
let deathsTotal = 0;
rows.forEach(row => {
const cols = row.split(",");
const date = cols[0];
const deathsCurrentLine = parseInt(cols[4]);
if (previousDate === date) {
dates.pop();
deaths.pop();
deathsTotal += deathsCurrentLine;
} else {
deathsTotal = deathsCurrentLine;
previousDate = date;
}
dates.push(date);
deaths.push(deathsTotal);
});
return { dates, deaths};
}
const hospData = await getHosp();
const casesData = await getCases();
const deathsData = await getDeaths();
// create date array with day, month and year
let dateArray = hospData.dates[hospData.dates.length - 2].split('-');
let day = dateArray[2];
let month = dateArray[1];
let year = dateArray[0];
// Styling variables
// Fonts
const TITLE_FONT = Font.systemFont(16);
const BODY_FONT = Font.thinMonospacedSystemFont(14);
// Colors
const TITLE_COLOR = new Color('#000000');
const BODY_COLOR = new Color('#000000');
// Widget creation
const widget = new ListWidget();
let gradient = new LinearGradient();
widget.backgroundColor = new Color('#E0DFD5');
widget.setPadding(20,20,20,20);
// load images
let hospitalInImageURL = 'https://belgium-covid-cases.netlify.app/hospital_in.png';
let hospitalInImage = await getImage(hospitalInImageURL);
let hospitalOutImageURL = 'https://belgium-covid-cases.netlify.app/hospital_out.png';
let hospitalOutImage = await getImage(hospitalOutImageURL);
let hospitalTotalImageURL = 'https://belgium-covid-cases.netlify.app/hospital_total.png';
let hospitalTotalImage = await getImage(hospitalTotalImageURL);
async function getImage(url) {
let req = new Request(url);
return await req.loadImage();
}
// Title
const titleText = widget.addText('🇧🇪 CORONA-STATS BELGIUM');
titleText.textColor = TITLE_COLOR;
titleText.font = TITLE_FONT;
widget.addSpacer(20);
// Hospitalisaties text
const HospitalisationsText = widget.addText(`HOSPITALISATIONS`);
HospitalisationsText.textColor = TITLE_COLOR;
HospitalisationsText.font = TITLE_FONT;
widget.addSpacer(10);
// TOP STACK
let topStack = widget.addStack();
topStack.setPadding(0, 15, 5, 15);
topStack.layoutHorizontally();
topStack.cornerRadius = 10;
topStack.cornerRadius = 10;
topStack.borderWidth = 2;
topStack.borderColor = new Color('#000000');
// top stack - left item
let topLeftStack = topStack.addStack();
topLeftStack.layoutVertically();
const hospitalInWidgetImage = topLeftStack.addImage(hospitalInImage);
hospitalInWidgetImage.imageSize = new Size(70, 50);
topLeftStack.addSpacer(8);
const hospitalInText = topLeftStack.addText(` ${hospData.newIns[hospData.totalIns.length - 2]}`);
hospitalInText.textColor = TITLE_COLOR;
hospitalInText.font = Font.systemFont(24);
topStack.addSpacer();
// top stack - center item
let topCenterStack = topStack.addStack();
topCenterStack.layoutVertically();
const hospitalOutWidgetImage = topCenterStack.addImage(hospitalOutImage);
hospitalOutWidgetImage.imageSize = new Size(70, 50);
topCenterStack.addSpacer(8);
const hospitalOutText = topCenterStack.addText(` ${hospData.newOuts[hospData.totalIns.length - 2]}`);
hospitalOutText.textColor = TITLE_COLOR;
hospitalOutText.font = Font.systemFont(24);
topStack.addSpacer();
// top stack - right item
let topRightStack = topStack.addStack();
topRightStack.layoutVertically();
const hospitalTotalWidgetImage = topRightStack.addImage(hospitalTotalImage);
hospitalTotalWidgetImage.imageSize = new Size(70, 50);
topRightStack.addSpacer(8);
const hospitalTotalText = topRightStack.addText(` ${hospData.totalIns[hospData.totalIns.length - 2]}`);
hospitalTotalText.textColor = TITLE_COLOR;
hospitalTotalText.font = Font.systemFont(24);
widget.addSpacer(20);
// below stack
const positiveToday = casesData.positives[casesData.positives.length - 2];
const testsTakenToday = casesData.tests[casesData.tests.length - 2];
const positiveYesterday = casesData.positives[casesData.positives.length - 3];
const testsTakenYesterday = casesData.tests[casesData.tests.length - 3];
const CasesText = widget.addText(`CASES`);
CasesText.textColor = TITLE_COLOR;
CasesText.font = TITLE_FONT;
widget.addSpacer(5);
const testsTakenText = widget.addText(`${positiveYesterday} cases out of ${testsTakenYesterday} tests (\
${((positiveYesterday / testsTakenYesterday) * 100).toFixed(1)}%)`);
testsTakenText.textColor = TITLE_COLOR;
testsTakenText.font = TITLE_FONT;
widget.addSpacer(20);
const deathsText = widget.addText(`DEATHS`);
deathsText.textColor = TITLE_COLOR;
deathsText.font = TITLE_FONT;
widget.addSpacer(5);
const deathsToday = deathsData.deaths[deathsData.deaths.length - 3];
const deathsNumberText = widget.addText(`${deathsToday}`);
deathsNumberText.textColor = TITLE_COLOR;
deathsNumberText.font = TITLE_FONT;
widget.addSpacer();
// subtitle displaying date
const subtitleText = widget.addText(`source: Sciensano - hospitalisations ${day}-${month}-${year}`);
subtitleText.textColor = BODY_COLOR;
subtitleText.font = Font.thinMonospacedSystemFont(11);
const subtitleText2 = widget.addText(`cases and death figures are from day before`);
subtitleText2.textColor = BODY_COLOR;
subtitleText2.font = Font.thinMonospacedSystemFont(11);
Script.setWidget(widget);
await widget.presentLarge();