diff --git a/server/scripts/modules/currentweather.js b/server/scripts/modules/currentweather.js index 6a8febd..1dcd83c 100644 --- a/server/scripts/modules/currentweather.js +++ b/server/scripts/modules/currentweather.js @@ -39,7 +39,7 @@ class CurrentWeather extends WeatherDisplay { } catch (e) { console.error('Unable to get current observations'); console.error(e); - this.setStatus(STATUS.error); + this.setStatus(STATUS.failed); return; } // we only get here if there was no error above diff --git a/server/scripts/modules/extendedforecast.js b/server/scripts/modules/extendedforecast.js index e0ef9fa..771d439 100644 --- a/server/scripts/modules/extendedforecast.js +++ b/server/scripts/modules/extendedforecast.js @@ -35,12 +35,12 @@ class ExtendedForecast extends WeatherDisplay { } catch (e) { console.error('Unable to get extended forecast'); console.error(e); - this.setStatus(STATUS.error); + this.setStatus(STATUS.failed); return; } // we only get here if there was no error above this.data = this.parseExtendedForecast(forecast.properties.periods); - this.screnIndex = 0; + this.screenIndex = 0; this.drawCanvas(); } diff --git a/server/scripts/modules/icons.js b/server/scripts/modules/icons.js index c66b501..8d46800 100644 --- a/server/scripts/modules/icons.js +++ b/server/scripts/modules/icons.js @@ -227,7 +227,7 @@ const icons = (() => { case 'tsra_hi': case 'tsra_hi-n': case 'hurricane': - return addPath('CC_TStorm'); + return addPath('CC_TStorm.gif'); case 'wind_few': case 'wind_sct': diff --git a/server/scripts/modules/localforecast.js b/server/scripts/modules/localforecast.js index 2625eff..866d26c 100644 --- a/server/scripts/modules/localforecast.js +++ b/server/scripts/modules/localforecast.js @@ -100,6 +100,7 @@ class LocalForecast extends WeatherDisplay { } catch (e) { console.error(`GetWeatherForecast failed: ${weatherParameters.forecast}`); console.error(e); + this.setStatus(STATUS.failed); return false; } } diff --git a/server/scripts/modules/radar.js b/server/scripts/modules/radar.js index 81ca921..efc7504 100644 --- a/server/scripts/modules/radar.js +++ b/server/scripts/modules/radar.js @@ -10,7 +10,29 @@ class Radar extends WeatherDisplay { this.dopplerRadarImageMax = 6; // update timing this.timing.baseDelay = 350; - this.timing.delay = [4,1,1,1,1,1,12]; + this.timing.delay = [ + {time: 4, si: 0}, + {time: 1, si: 1}, + {time: 1, si: 2}, + {time: 1, si: 3}, + {time: 1, si: 4}, + {time: 1, si: 5}, + {time: 4, si: 6}, + {time: 1, si: 0}, + {time: 1, si: 1}, + {time: 1, si: 2}, + {time: 1, si: 3}, + {time: 1, si: 4}, + {time: 1, si: 5}, + {time: 4, si: 6}, + {time: 1, si: 0}, + {time: 1, si: 1}, + {time: 1, si: 2}, + {time: 1, si: 3}, + {time: 1, si: 4}, + {time: 1, si: 5}, + {time: 12, si: 6}, + ]; // pre-load background image (returns promise) this.backgroundImage = utils.image.load('images/BackGround4_1.png'); @@ -47,7 +69,7 @@ class Radar extends WeatherDisplay { } catch (e) { console.error('Unable to get list of radars'); console.error(e); - this.setStatus(STATUS.error); + this.setStatus(STATUS.failed); return; } @@ -190,9 +212,8 @@ class Radar extends WeatherDisplay { this.timing.totalScreens = radarInfo.length; // store the images this.data = radarInfo.map(radar=>radar.canvas); - + this.times = radarInfo.map(radar=>radar.time); - this.drawCanvas(); } async drawCanvas() { diff --git a/server/scripts/modules/weatherdisplay.js b/server/scripts/modules/weatherdisplay.js index c5019bb..75a7fa1 100644 --- a/server/scripts/modules/weatherdisplay.js +++ b/server/scripts/modules/weatherdisplay.js @@ -27,7 +27,7 @@ class WeatherDisplay { delay: 1, // 1*1second = 1 second total display time }; this.navBaseCount = 0; - this.screenIndex = 0; + this.screenIndex = -1; // special starting condition this.setStatus(STATUS.loading); this.createCanvas(elemId); @@ -65,21 +65,8 @@ class WeatherDisplay { // set status this.setStatus(STATUS.loading); - // set up the timing delays - if (Array.isArray(this.timing.delay) && typeof this.timing.delay[0] === 'number') { - // array is defined as how long each screen should be displayed. This needs to be converted into total time for use here - if (!this.timing.fullDelay) { - let sum = 0; - this.timing.fullDelay = this.timing.delay.map(val => { - const calc = sum + val; - sum += val; - return calc; - }); - } - } - - // update total screens - if (Array.isArray(this.timing.delay)) this.timing.totalScreens = this.timing.delay.length; + // recalculate navigation timing (in case it was modified in the constructor) + this.calcNavTiming(); } drawCanvas() { @@ -104,9 +91,7 @@ class WeatherDisplay { // if (_ScrollText !== '') OkToDrawCustomScrollText = true; if (this.elemId === 'almanac') OkToDrawNoaaImage = false; if (this.elemId === 'travelForecast') OkToDrawNoaaImage = false; - if (this.elemId === 'regionalForecast0') OkToDrawNoaaImage = false; - if (this.elemId === 'regionalForecast1') OkToDrawNoaaImage = false; - if (this.elemId === 'regionalForecast2') OkToDrawNoaaImage = false; + if (this.elemId === 'regionalForecast') OkToDrawNoaaImage = false; if (this.elemId === 'radar') { OkToDrawCurrentConditions = false; OkToDrawCurrentDateTime = false; @@ -228,12 +213,6 @@ class WeatherDisplay { // reset timing this.startNavCount(navigation.isPlaying()); - - // if there was a command the canvas has already been drawn - if (navCmd) return; - - // refresh the canvas (in case the screen index changed) - if (navCmd) this.drawCanvas(); } hideCanvas() { this.stopNavBaseCount(true); @@ -263,21 +242,70 @@ class WeatherDisplay { // call base count change if available for this function if (this.baseCountChange) this.baseCountChange(this.navBaseCount); - // determine type of timing - // simple delay - if (typeof this.timing.delay === 'number') { - this.navNext(); + // handle base count/screen index changes + this.updateScreenFromBaseCount(); + } + + updateScreenFromBaseCount() { + // get the next screen index + let nextScreenIndex = this.screenIndexFromBaseCount(); + + // special cases for first and last frame + // must compare with false as nextScreenIndex could be 0 which is valid + if (nextScreenIndex === false) { + this.sendNavDisplayMessage(navigation.msg.response.next); + this.stopNavBaseCount(); return; } - // array of timing integers - if (Array.isArray(this.timing.delay) && typeof this.timing.delay[0] === 'number') { - // scan the array for a matching number and calculate new screen index from the number - const timingMatch = this.timing.fullDelay.indexOf(this.navBaseCount); - // if not found return - if (timingMatch < 0 && this.navBaseCount <= this.timing.fullDelay[this.timing.totalScreens-1]) return; - // navigate to the next screen - this.navNext(); + // test for no change and exit early + if (nextScreenIndex === this.screenIndex) return; + + this.screenIndex = nextScreenIndex; + + // call the appropriate screen index change method + if (!this.screenIndexChange) { + this.drawCanvas(); + } else { + this.screenIndexChange(this.screenIndex); + } + } + + // take the three timing formats shown above and break them into arrays for consistent usage in navigation functions + // this.timing.fullDelay = [end of screen index 0 in base counts, end of screen index 1...] + // this.timing.screenIndexes = [screen index to use during this.timing.fullDelay[0], screen index to use during this.timing.fullDelay[1], ...] + calcNavTiming() { + // update total screens + if (Array.isArray(this.timing.delay)) this.timing.totalScreens = this.timing.delay.length; + + // if the delay is provided as a single value, expand it to a series of the same value + let intermediateDelay = []; + if (typeof this.timing.delay === 'number') { + for (let i = 0; i < this.timing.totalScreens; i++) intermediateDelay.push(this.timing.delay); + } else { + // map just the delays to the intermediate block + intermediateDelay = this.timing.delay.map(delay => { + if (typeof delay === 'object') return delay.time; + return delay; + }); + } + + // calculate the cumulative end point of each delay + let sum = 0; + this.timing.fullDelay = intermediateDelay.map(val => { + const calc = sum + val; + sum += val; + return calc; + }); + + // generate a list of screen either sequentially if not provided in an object or from the object + if (Array.isArray(this.timing.delay) && typeof this.timing.delay[0] === 'object') { + // extract screen indexes from objects + this.timing.screenIndexes = this.timing.delay.map(delay => delay.si); + } else { + // generate sequential screen indexes + this.timing.screenIndexes = []; + for (let i = 0; i < this.timing.totalScreens; i++) this.timing.screenIndexes.push(i); } } @@ -287,62 +315,40 @@ class WeatherDisplay { if (command === navigation.msg.command.firstFrame) { this.resetNavBaseCount(); } else { - // increment screen index - this.screenIndex++; + // set the base count to the next available frame + const newBaseCount = this.timing.fullDelay.find(delay => delay > this.navBaseCount); + this.navBaseCount = newBaseCount; } - // test for end reached - if (this.screenIndex >= this.timing.totalScreens) { - this.screenIndex = this.timing.totalScreens - 1; - this.sendNavDisplayMessage(navigation.msg.response.next); - this.stopNavBaseCount(); - return; - } - this.baseCountFromScreenIndex(); - // if the end was not reached, update the canvas (typical), or run a callback (atypical) - if (!this.screenIndexChange) { - this.drawCanvas(); - } else { - this.screenIndexChange(this.screenIndex); - } - this.showCanvas(); + this.updateScreenFromBaseCount(); } // navigate to previous screen navPrev(command) { // check for special 'last frame' command if (command === navigation.msg.command.lastFrame) { - this.screenIndex = this.timing.totalScreens-1; + this.navBaseCount = this.timing.fullDelay[this.timing.totalScreens-1]-1; } else { - // decrement screen index - this.screenIndex--; + // find the highest fullDelay that is less than the current base count + const newBaseCount = this.timing.fullDelay.reduce((acc, delay) => { + if (delay < this.navBaseCount) return delay; + return acc; + },0); + // if the new base count is zero then we're already at the first screen + if (newBaseCount === 0 && this.navBaseCount === 0) { + this.sendNavDisplayMessage(navigation.msg.response.previous); + return; + } + this.navBaseCount = newBaseCount; } - - // test for end reached - if (this.screenIndex < 0) { - this.screenIndex = 0; - this.sendNavDisplayMessage(navigation.msg.response.previous); - return; - } - this.baseCountFromScreenIndex(); - // if the end was not reached, update the canvas (typical), or run a callback (atypical) - if (!this.screenIndexChange) { - this.drawCanvas(); - } else { - this.screenIndexChange(this.screenIndex); - } - this.showCanvas(); + this.updateScreenFromBaseCount(); } - // calculate a baseCount from the screen index for the array timings - baseCountFromScreenIndex() { - if (!Array.isArray(this.timing.delay)) return; - // first screen starts at zero - if (this.screenIndex === 0) { - this.navBaseCount = 0; - return; - } - // otherwise return one more than the previous sum - this.navBaseCount = this.timing.fullDelay[this.screenIndex]; + // get the screen index for the current base count, returns false if past end of timing array (go to next screen, stop timing) + screenIndexFromBaseCount() { + // find the first timing in the timing array that is greater than the base count + const timingIndex = this.timing.fullDelay.findIndex(delay => delay > this.navBaseCount); + if (timingIndex === -1) return false; + return this.timing.screenIndexes[timingIndex]; } // start and stop base counter @@ -357,7 +363,7 @@ class WeatherDisplay { } resetNavBaseCount() { this.navBaseCount = 0; - this.screenIndex = 0; + this.screenIndex = -1; } sendNavDisplayMessage(message) {