From b870ce1c01fdd71e07da3e2ff112474b8f0aa22a Mon Sep 17 00:00:00 2001 From: Matt Walsh Date: Fri, 27 Jun 2025 15:29:20 -0500 Subject: [PATCH 1/2] store already processed radar images for reuse on silent reload --- server/scripts/modules/radar.mjs | 44 +++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/server/scripts/modules/radar.mjs b/server/scripts/modules/radar.mjs index de838e3..418fe60 100644 --- a/server/scripts/modules/radar.mjs +++ b/server/scripts/modules/radar.mjs @@ -8,6 +8,10 @@ import * as utils from './radar-utils.mjs'; import setTiles from './radar-tiles.mjs'; import processRadar from './radar-processor.mjs'; +// store processed radar as dataURLs to avoid re-processing frames as they slide backwards in time +// this is cleared upon changing the location displayed +let processedRadars = []; + const RADAR_HOST = 'mesonet.agron.iastate.edu'; class Radar extends WeatherDisplay { constructor(navId, elemId) { @@ -110,19 +114,44 @@ class Radar extends WeatherDisplay { elemId: this.elemId, }); + const radarKey = `${radarSourceXY.x.toFixed(0)}-${radarSourceXY.y.toFixed(0)}`; + + // reset the "used" flag on pre-processed radars + // items that were not used during this process are deleted (either expired via time or change of location) + processedRadars.forEach((radar) => { radar.used = false; }); + // remove any radars that aren't + // Load the most recent doppler radar images. const radarInfo = await Promise.all(urls.map(async (url) => { - const processedRadar = await processRadar({ + // store the time + const timeMatch = url.match(/_(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)\./); + const [, year, month, day, hour, minute] = timeMatch; + + const radarKeyedTimestamp = `${radarKey}:${year}${month}${day}${hour}${minute}`; + + // check for a pre-processed radar + const preProcessed = processedRadars.find((radar) => radar.key === radarKeyedTimestamp); + + // use the pre-processed radar, or get a new one + const processedRadar = preProcessed?.dataURL ?? await processRadar({ url, RADAR_HOST, OVERRIDES, radarSourceXY, }); - // store the time - const timeMatch = url.match(/_(\d{4})(\d\d)(\d\d)(\d\d)(\d\d)\./); + // store the radar + if (!preProcessed) { + processedRadars.push({ + key: radarKeyedTimestamp, + dataURL: processedRadar, + used: true, + }); + } else { + // set used flag + preProcessed.used = true; + } - const [, year, month, day, hour, minute] = timeMatch; const time = DateTime.fromObject({ year, month, @@ -150,12 +179,15 @@ class Radar extends WeatherDisplay { this.times = radarInfo.map((radar) => radar.time); this.setStatus(STATUS.loaded); + + // clean up any unused stored radars + processedRadars = processedRadars.filter((radar) => radar.used); } async drawCanvas() { super.drawCanvas(); const time = this.times[this.screenIndex].toLocaleString(DateTime.TIME_SIMPLE); - const timePadded = time.length >= 8 ? time : ` ${time}`; + const timePadded = time.length >= 8 ? time : ` ${time} `; this.elem.querySelector('.header .right .time').innerHTML = timePadded; // get image offset calculation @@ -163,7 +195,7 @@ class Radar extends WeatherDisplay { const actualFrameHeight = this.elem.querySelector('.frame').scrollHeight; // scroll to image - this.elem.querySelector('.scroll-area').style.top = `${-this.screenIndex * actualFrameHeight}px`; + this.elem.querySelector('.scroll-area').style.top = `${-this.screenIndex * actualFrameHeight} px`; this.finishDraw(); } From 8a2907e02c83f7fb142a616a8889b87a48ac7981 Mon Sep 17 00:00:00 2001 From: Matt Walsh Date: Fri, 27 Jun 2025 15:35:15 -0500 Subject: [PATCH 2/2] fix display of null wind speed --- server/scripts/modules/currentweather.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/server/scripts/modules/currentweather.mjs b/server/scripts/modules/currentweather.mjs index 4280c1a..b09d216 100644 --- a/server/scripts/modules/currentweather.mjs +++ b/server/scripts/modules/currentweather.mjs @@ -112,10 +112,12 @@ class CurrentWeather extends WeatherDisplay { condition = shortConditions(condition); } + const wind = (typeof this.data.WindSpeed === 'number') ? this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' ') : '-'; + const fill = { temp: this.data.Temperature + String.fromCharCode(176), condition, - wind: this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' '), + wind, location: locationCleanup(this.data.station.properties.name).substr(0, 20), humidity: `${this.data.Humidity}%`, dewpoint: this.data.DewPoint + String.fromCharCode(176), @@ -202,7 +204,6 @@ const parseData = (data) => { data.WindSpeed = windConverter(observations.windSpeed.value); data.WindDirection = directionToNSEW(observations.windDirection.value); data.WindGust = windConverter(observations.windGust.value); - data.WindSpeed = windConverter(data.WindSpeed); data.WindUnit = windConverter.units; data.Humidity = Math.round(observations.relativeHumidity.value); data.Icon = getLargeIcon(observations.icon);