import { aq, op } from"@uwdata/arquero"bucket_base ="https://d33173dkfxwa5x.cloudfront.net/www/"FA = FileAttachment
Here’s how the rest of Australia looks today so far.
nowHour = (newDate()).getUTCHours()nowHour >=10&& nowHour <=22?md`Some places may still be cooling off as the night continues.`:md`Some places may still be heating up as the day continues.`
statsAllRaw =FA(bucket_base +"stats/stats_all.json").json()// statsAllRaw is an object with keys by station id, but we// need an array with an id field. let's move the ids instatsAll = {const statsArray = []Object.keys(statsAllRaw).map(k => statsArray.push({...statsAllRaw[k],id: k}))const tidiedStats = aq.from(statsArray).derive({lat: d => op.parse_float(d.isit_lat),lon: d => op.parse_float(d.isit_lon),isit_average: d => op.parse_float(d.isit_average),// current? (that's the actual avg temp)isit_maximum: d => op.parse_float(d.isit_maximum),isit_minimum: d => op.parse_float(d.isit_minimum),max_when: d => op.parse_date(d.isit_maximum_dt),min_when: d => op.parse_date(d.isit_minimum_dt),slug: d => op.replace( op.replace( op.replace( op.lower(d.isit_label),/\s-\s/g,"-"),/\s/g,"-"),/[()]/g,"") })// mark as stale if latest obs are > 24 hours old.derive({max_stale: d => ((d.max_when- op.now()) / (1000*60)) / (24*60) >1,min_stale: d => ((d.min_when- op.now()) / (1000*60)) / (24*60) >1 }).objects()return(tidiedStats)}
australia =FileAttachment("/assets/australia.geojson").json()Plot =import("https://esm.run/@observablehq/plot")answer_domain = ["Hell no!","No!","Nope","Not really","Yup","Yeah!","Hell yeah!"]Plot.plot({projection: {type:"equirectangular",rotate: [-133,28],domain: d3.geoCircle().center([133,-28]).radius(18)() },marks: [// Plot.graticule(), Plot.geo(australia, {fill:"#00000009",stroke:"#dddddd" }),// replace stale locations with crosses Plot.dot(staleStats, {x:"lon",y:"lat",stroke:"lightgrey",r:6,symbol:"times" }), Plot.dot(currentStats, {x:"lon",y:"lat",fill:"isit_answer",stroke: d => d.isit_answer=="Hell no!"|| d.isit_answer=="Hell yeah!"?"black":"#00000099",strokeWidth:0.75,r:6, }), Plot.tip(currentStats, tipTemplate),// enlarge dot you're pointing to Plot.dot(currentStats, Plot.pointer({x:"lon",y:"lat",fill:"isit_answer",stroke: d => d.isit_answer=="Hell no!"|| d.isit_answer=="Hell yeah!"?"black":"#00000099",strokeWidth:0.75,r:12, })),// enlargen clickable areas with invisible voronoi polys Plot.voronoi(currentStats, {x:"lon",y:"lat",fill:"transparent",stroke:"transparent",href: d =>"/places/"+ d.slug, }), ],color: {type:"ordinal",domain: answer_domain,range: ["#2166acff","#67a9cfff","#d1e5f0ff","#f7f7f7ff","#fddbc7ff","#ef8a62ff","#b2182bff"] },height:600})
// breaking out the pointer layer for readability// (and in case we decide to customise it later)tipTemplate = Plot.pointer({x:"lon",y:"lat",channels: {place: {label:"",value: d => d.isit_label, },label: {label:"",value: d => d.isit_comment },separator: {label:"",value: d =>"" },isit_maximum: {label:"Max:",value: d => d.isit_maximum+"°C" },isit_minimum: {label:"Min:",value: d => d.isit_minimum+"°C" } },fontSize:20,fontFamily:"Roboto Condensed",format: {x:null,y:null },lineWidth:20,lineHeight:1.25,pointerSize:0,fillOpacity:0.8,strokeOpacity:0})