more consistent navigation control

This commit is contained in:
Matt Walsh 2020-09-09 14:29:03 -05:00
parent 1f688318b5
commit 9a09ccd1ea
6 changed files with 119 additions and 91 deletions

View file

@ -39,7 +39,7 @@ class CurrentWeather extends WeatherDisplay {
} catch (e) { } catch (e) {
console.error('Unable to get current observations'); console.error('Unable to get current observations');
console.error(e); console.error(e);
this.setStatus(STATUS.error); this.setStatus(STATUS.failed);
return; return;
} }
// we only get here if there was no error above // we only get here if there was no error above

View file

@ -35,12 +35,12 @@ class ExtendedForecast extends WeatherDisplay {
} catch (e) { } catch (e) {
console.error('Unable to get extended forecast'); console.error('Unable to get extended forecast');
console.error(e); console.error(e);
this.setStatus(STATUS.error); this.setStatus(STATUS.failed);
return; return;
} }
// we only get here if there was no error above // we only get here if there was no error above
this.data = this.parseExtendedForecast(forecast.properties.periods); this.data = this.parseExtendedForecast(forecast.properties.periods);
this.screnIndex = 0; this.screenIndex = 0;
this.drawCanvas(); this.drawCanvas();
} }

View file

@ -227,7 +227,7 @@ const icons = (() => {
case 'tsra_hi': case 'tsra_hi':
case 'tsra_hi-n': case 'tsra_hi-n':
case 'hurricane': case 'hurricane':
return addPath('CC_TStorm'); return addPath('CC_TStorm.gif');
case 'wind_few': case 'wind_few':
case 'wind_sct': case 'wind_sct':

View file

@ -100,6 +100,7 @@ class LocalForecast extends WeatherDisplay {
} catch (e) { } catch (e) {
console.error(`GetWeatherForecast failed: ${weatherParameters.forecast}`); console.error(`GetWeatherForecast failed: ${weatherParameters.forecast}`);
console.error(e); console.error(e);
this.setStatus(STATUS.failed);
return false; return false;
} }
} }

View file

@ -10,7 +10,29 @@ class Radar extends WeatherDisplay {
this.dopplerRadarImageMax = 6; this.dopplerRadarImageMax = 6;
// update timing // update timing
this.timing.baseDelay = 350; 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) // pre-load background image (returns promise)
this.backgroundImage = utils.image.load('images/BackGround4_1.png'); this.backgroundImage = utils.image.load('images/BackGround4_1.png');
@ -47,7 +69,7 @@ class Radar extends WeatherDisplay {
} catch (e) { } catch (e) {
console.error('Unable to get list of radars'); console.error('Unable to get list of radars');
console.error(e); console.error(e);
this.setStatus(STATUS.error); this.setStatus(STATUS.failed);
return; return;
} }
@ -192,7 +214,6 @@ class Radar extends WeatherDisplay {
this.data = radarInfo.map(radar=>radar.canvas); this.data = radarInfo.map(radar=>radar.canvas);
this.times = radarInfo.map(radar=>radar.time); this.times = radarInfo.map(radar=>radar.time);
this.drawCanvas();
} }
async drawCanvas() { async drawCanvas() {

View file

@ -27,7 +27,7 @@ class WeatherDisplay {
delay: 1, // 1*1second = 1 second total display time delay: 1, // 1*1second = 1 second total display time
}; };
this.navBaseCount = 0; this.navBaseCount = 0;
this.screenIndex = 0; this.screenIndex = -1; // special starting condition
this.setStatus(STATUS.loading); this.setStatus(STATUS.loading);
this.createCanvas(elemId); this.createCanvas(elemId);
@ -65,21 +65,8 @@ class WeatherDisplay {
// set status // set status
this.setStatus(STATUS.loading); this.setStatus(STATUS.loading);
// set up the timing delays // recalculate navigation timing (in case it was modified in the constructor)
if (Array.isArray(this.timing.delay) && typeof this.timing.delay[0] === 'number') { this.calcNavTiming();
// 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;
} }
drawCanvas() { drawCanvas() {
@ -104,9 +91,7 @@ class WeatherDisplay {
// if (_ScrollText !== '') OkToDrawCustomScrollText = true; // if (_ScrollText !== '') OkToDrawCustomScrollText = true;
if (this.elemId === 'almanac') OkToDrawNoaaImage = false; if (this.elemId === 'almanac') OkToDrawNoaaImage = false;
if (this.elemId === 'travelForecast') OkToDrawNoaaImage = false; if (this.elemId === 'travelForecast') OkToDrawNoaaImage = false;
if (this.elemId === 'regionalForecast0') OkToDrawNoaaImage = false; if (this.elemId === 'regionalForecast') OkToDrawNoaaImage = false;
if (this.elemId === 'regionalForecast1') OkToDrawNoaaImage = false;
if (this.elemId === 'regionalForecast2') OkToDrawNoaaImage = false;
if (this.elemId === 'radar') { if (this.elemId === 'radar') {
OkToDrawCurrentConditions = false; OkToDrawCurrentConditions = false;
OkToDrawCurrentDateTime = false; OkToDrawCurrentDateTime = false;
@ -228,12 +213,6 @@ class WeatherDisplay {
// reset timing // reset timing
this.startNavCount(navigation.isPlaying()); 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() { hideCanvas() {
this.stopNavBaseCount(true); this.stopNavBaseCount(true);
@ -263,21 +242,70 @@ class WeatherDisplay {
// call base count change if available for this function // call base count change if available for this function
if (this.baseCountChange) this.baseCountChange(this.navBaseCount); if (this.baseCountChange) this.baseCountChange(this.navBaseCount);
// determine type of timing // handle base count/screen index changes
// simple delay this.updateScreenFromBaseCount();
if (typeof this.timing.delay === 'number') { }
this.navNext();
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; return;
} }
// array of timing integers // test for no change and exit early
if (Array.isArray(this.timing.delay) && typeof this.timing.delay[0] === 'number') { if (nextScreenIndex === this.screenIndex) return;
// scan the array for a matching number and calculate new screen index from the number
const timingMatch = this.timing.fullDelay.indexOf(this.navBaseCount); this.screenIndex = nextScreenIndex;
// if not found return
if (timingMatch < 0 && this.navBaseCount <= this.timing.fullDelay[this.timing.totalScreens-1]) return; // call the appropriate screen index change method
// navigate to the next screen if (!this.screenIndexChange) {
this.navNext(); 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) { if (command === navigation.msg.command.firstFrame) {
this.resetNavBaseCount(); this.resetNavBaseCount();
} else { } else {
// increment screen index // set the base count to the next available frame
this.screenIndex++; const newBaseCount = this.timing.fullDelay.find(delay => delay > this.navBaseCount);
this.navBaseCount = newBaseCount;
} }
// test for end reached this.updateScreenFromBaseCount();
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();
} }
// navigate to previous screen // navigate to previous screen
navPrev(command) { navPrev(command) {
// check for special 'last frame' command // check for special 'last frame' command
if (command === navigation.msg.command.lastFrame) { if (command === navigation.msg.command.lastFrame) {
this.screenIndex = this.timing.totalScreens-1; this.navBaseCount = this.timing.fullDelay[this.timing.totalScreens-1]-1;
} else { } else {
// decrement screen index // find the highest fullDelay that is less than the current base count
this.screenIndex--; 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;
} }
this.updateScreenFromBaseCount();
// 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();
} }
// calculate a baseCount from the screen index for the array timings // get the screen index for the current base count, returns false if past end of timing array (go to next screen, stop timing)
baseCountFromScreenIndex() { screenIndexFromBaseCount() {
if (!Array.isArray(this.timing.delay)) return; // find the first timing in the timing array that is greater than the base count
// first screen starts at zero const timingIndex = this.timing.fullDelay.findIndex(delay => delay > this.navBaseCount);
if (this.screenIndex === 0) { if (timingIndex === -1) return false;
this.navBaseCount = 0; return this.timing.screenIndexes[timingIndex];
return;
}
// otherwise return one more than the previous sum
this.navBaseCount = this.timing.fullDelay[this.screenIndex];
} }
// start and stop base counter // start and stop base counter
@ -357,7 +363,7 @@ class WeatherDisplay {
} }
resetNavBaseCount() { resetNavBaseCount() {
this.navBaseCount = 0; this.navBaseCount = 0;
this.screenIndex = 0; this.screenIndex = -1;
} }
sendNavDisplayMessage(message) { sendNavDisplayMessage(message) {