-
-
Save nickolasb/f929ef006107f9c474e66ccedd9bacc7 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Examples of Parameters: | |
// { "areaType" : "ltla" , "areaName" : "Westminster" , "cases" : "newCasesBySpecimenDate" , "accentColor" : "#99ff99" } | |
// { "areaType" : "utla" , "areaName" : "Hackney and City of London" , "cases" : "newCasesBySpecimenDate" , "accentColor" : "#33cc33" } | |
// { "areaType" : "region" , "areaName" : "South East" , "cases" : "newCasesByPublishDate" , "accentColor" : "#009900" } | |
// { "areaType" : "nation" , "areaName" : "England" , "cases" : "newCasesByPublishDate" , "accentColor" : "#009900" } | |
// USER DEFINITIONS | |
const lineWeight = 2 | |
const vertLineWeight = .5 | |
// Widget Params, default values for debugging | |
const widgetParams = JSON.parse((args.widgetParameter != null) ? args.widgetParameter : '{ "areaType" : "utla" , "areaName" : "Hackney and City of London" , "cases" : "newCasesBySpecimenDate" , "accentColor" : "#33cc33" }') | |
// DON'T CHANGE THE VALUES BELOW | |
const widgetHeight = 338 | |
const widgetWidth = 720 | |
const areaType = widgetParams.areaType | |
const areaName = widgetParams.areaName | |
const cases = widgetParams.cases | |
const accentColor1 = new Color(widgetParams.accentColor, 1) | |
const accentColor2 = Color.lightGray() | |
// Number of days to show | |
const daysToShow = 15 | |
// space in pixels between the days | |
const spaceBetweenDays = 44.5 | |
// POSITION AND SIZE | |
// All coordinates make reference to the top-left of the element. | |
// Title Name | |
const titleFontSize = 20 | |
const titleFont = Font.systemFont(titleFontSize) | |
const titlePos = new Point(25, 15) | |
// Location Name | |
const areaNameFontSize = 36 | |
const areaNameFont = Font.semiboldSystemFont(areaNameFontSize) | |
const areaNameCoords = new Point(25, 38) | |
// Cases | |
const casesFontSize = 22 | |
const casesFont = Font.systemFont(casesFontSize) | |
// Hour | |
const dayFontSize = 22 | |
const dayFont = Font.systemFont(dayFontSize) | |
// Supported widget sized: medium | |
let drawContext = new DrawContext(); | |
drawContext.size = new Size(widgetWidth, widgetHeight) | |
drawContext.opaque = false | |
// Retrieve data | |
let url = "https://api.coronavirus.data.gov.uk/v1/data?filters=areaType=" + areaType + ";areaName=" + areaName + "&structure={\"date\":\"date\",\"cases\":\"" + cases + "\"}" | |
url = encodeURI(url) | |
let req = new Request(url) | |
let json = await req.loadJSON() | |
let data = json.data | |
// Create widget | |
let widget = new ListWidget(); | |
widget.setPadding(0, 0, 0, 0); | |
// Title | |
drawTextP("COVID-19 Cases", titlePos, Color.white(), titleFont); | |
// Location | |
drawContext.setTextAlignedLeft() | |
drawTextP(capitalize(areaName), areaNameCoords, accentColor1, areaNameFont); | |
// Find min, max | |
let min, max, diff; | |
for(let i = 0; i < daysToShow; i++) { | |
let aux = data[i].cases | |
min = (aux < min || min == undefined ? aux : min) | |
max = (aux > max || max == undefined ? aux : max) | |
} | |
diff = max - min; | |
const graphLow = 280 | |
const graphHeight = 160 | |
// FOR EACH DAY | |
drawContext.setTextAlignedCenter() | |
for (let i = (daysToShow - 1), j = 0; i >= 0; i--, j++) { | |
let day = (new Date(data[i].date)).getDate() | |
let dayOfWeek = (new Date(data[i].date)).getDay() | |
let cases = data[i].cases | |
let delta = (cases - min) / diff | |
if (i > 0) { | |
let nextCases = data[i - 1].cases | |
let nextDelta = (nextCases - min) / diff | |
let point1 = new Point(spaceBetweenDays * j + 50, graphLow - (graphHeight * delta)) | |
let point2 = new Point(spaceBetweenDays * (j+1) + 50, graphLow - (graphHeight * nextDelta)) | |
drawLine(point1, point2, lineWeight, accentColor1) | |
} | |
// Vertical Line | |
let point1 = new Point(spaceBetweenDays * j + 50, graphLow - (graphHeight * delta)) | |
let point2 = new Point(spaceBetweenDays * j + 50, graphLow) | |
drawLine(point1, point2, vertLineWeight, accentColor2) | |
let dayColor | |
if (dayOfWeek == 0 || dayOfWeek == 6) { | |
dayColor = accentColor2 | |
} else { | |
dayColor = Color.white() | |
} | |
// Cases | |
let casesRect = new Rect(spaceBetweenDays * j + 20, (graphLow - 40) - (graphHeight * delta), 60, casesFontSize + 1) | |
drawTextR(roundIfNeeded(cases), casesRect, dayColor, casesFont) | |
// Day | |
let dayRect = new Rect(spaceBetweenDays * j + 27, graphLow + 10, 50, dayFontSize + 1) | |
drawTextR(day, dayRect, dayColor, dayFont) | |
} | |
// Background | |
widget.backgroundColor = new Color("#444444", 1) | |
// Present | |
widget.backgroundImage = (drawContext.getImage()) | |
widget.presentMedium() | |
// FUNCTIONS | |
function roundIfNeeded(n) { | |
if (Math.floor(n / 1000) > 0) { | |
return (Math.round(n / 100) / 10) + "k" | |
} | |
return n | |
} | |
function capitalize(string) { | |
return string.replace(/\b\w/g, l=>l.toUpperCase()) | |
} | |
function drawTextP(text, point, color, font) { | |
drawContext.setFont(font) | |
drawContext.setTextColor(color) | |
drawContext.drawText(new String(text).toString(), point) | |
} | |
function drawTextR(text, rect, color, font) { | |
drawContext.setFont(font) | |
drawContext.setTextColor(color) | |
drawContext.drawTextInRect(new String(text).toString(), rect) | |
} | |
// function drawImage(image, x, y){ | |
// drawContext.drawImageAtPoint(image, new Point(x, y)) | |
// } | |
function drawLine(point1, point2, width, color){ | |
const path = new Path() | |
path.move(point1) | |
path.addLine(point2) | |
drawContext.addPath(path) | |
drawContext.setStrokeColor(color) | |
drawContext.setLineWidth(width) | |
drawContext.strokePath() | |
} | |
Script.complete() |
Hi,
When you add the widget there are 3 fields to configure: “Script”, “When interacting”, “Parameter”.
In “Parameter” you need to pass the region you want to see (If you don’t pass an argument a default value is used to ensure some data is shown). This way it’s possible to have multiple widgets showing different regions.
There are four examples on lines 2-5 of the script showing how to select the lower and upper authorities, region and nation. You probably know the name of the local authorities where you live. If you don’t, please send a message your post code and I’ll reply to you.
Thanks
I think it’s possible to improve the script to gather your location info too... maybe I’ll do it :)
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hey thank you for making this, how does one change the location? Mine says Hackney and London.