mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-17 00:59:29 -07:00
marine hourly mjs
This commit is contained in:
@@ -141,6 +141,7 @@ const parseForecast = async (data) => {
|
||||
const iceAccumulation = expand(data.iceAccumulation.values); // ice icon
|
||||
const probabilityOfPrecipitation = expand(data.probabilityOfPrecipitation.values); // rain icon
|
||||
const snowfallAmount = expand(data.snowfallAmount.values); // snow icon
|
||||
const waveHeight = expand(data.waveHeight.values);
|
||||
|
||||
const icons = await determineIcon(skyCover, weather, iceAccumulation, probabilityOfPrecipitation, snowfallAmount, windSpeed);
|
||||
|
||||
@@ -152,6 +153,7 @@ const parseForecast = async (data) => {
|
||||
probabilityOfPrecipitation: probabilityOfPrecipitation[idx],
|
||||
skyCover: skyCover[idx],
|
||||
icon: icons[idx],
|
||||
waveHeight: waveHeight[idx],
|
||||
}));
|
||||
};
|
||||
|
||||
|
||||
139
server/scripts/modules/marineforecast.mjs
Normal file
139
server/scripts/modules/marineforecast.mjs
Normal file
@@ -0,0 +1,139 @@
|
||||
// display extended forecast graphically
|
||||
// technically uses the same data as the local forecast, we'll let the browser do the caching of that
|
||||
|
||||
import STATUS from './status.mjs';
|
||||
import WeatherDisplay from './weatherdisplay.mjs';
|
||||
import { registerDisplay } from './navigation.mjs';
|
||||
import getExtendedForecast from './extendedforecast.mjs';
|
||||
import getHourlyForecast from './hourly.mjs';
|
||||
|
||||
class MarineForecast extends WeatherDisplay {
|
||||
constructor(navId, elemId) {
|
||||
super(navId, elemId, 'Marine Forecast', false);
|
||||
// this.showOnProgress = false;
|
||||
|
||||
// set timings
|
||||
this.timing.totalScreens = 1;
|
||||
}
|
||||
|
||||
async getData() {
|
||||
if (!super.getData()) return;
|
||||
|
||||
const [extendedForecast, hourlyForecast] = await Promise.all([
|
||||
getExtendedForecast(() => this.stillWaiting()),
|
||||
getHourlyForecast(() => this.stillWaiting()),
|
||||
]);
|
||||
if (extendedForecast === undefined || hourlyForecast === undefined) {
|
||||
this.setStatus(STATUS.failed);
|
||||
return;
|
||||
}
|
||||
|
||||
// test for all wave heights = 0, no data for wave heights
|
||||
if (hourlyForecast.every((value) => !value.waveHeight)) {
|
||||
// total screens = 0 to skip this display
|
||||
this.totalScreens = 0;
|
||||
this.setStatus(STATUS.noData);
|
||||
return;
|
||||
}
|
||||
|
||||
this.data = {
|
||||
extendedForecast,
|
||||
hourlyForecast,
|
||||
};
|
||||
this.screenIndex = 0;
|
||||
this.setStatus(STATUS.loaded);
|
||||
}
|
||||
|
||||
async drawCanvas() {
|
||||
super.drawCanvas();
|
||||
|
||||
// determine bounds
|
||||
// grab the first three or second set of three array elements
|
||||
const forecast = this.data.slice(0, 2);
|
||||
|
||||
// create each day template
|
||||
const days = forecast.map((Day) => {
|
||||
const fill = {};
|
||||
fill.date = Day.dayName;
|
||||
fill['wind-dir'] = 'NW';
|
||||
fill['wind-speed'] = '10 - 15kts';
|
||||
fill['wave-height'] = '1\'';
|
||||
fill['wave-desc'] = '';
|
||||
|
||||
const { low } = Day;
|
||||
if (low !== undefined) {
|
||||
fill['value-lo'] = Math.round(low);
|
||||
}
|
||||
const { high } = Day;
|
||||
fill['value-hi'] = Math.round(high);
|
||||
fill.condition = Day.text;
|
||||
|
||||
// draw the icon
|
||||
fill['wave-icon'] = { type: 'img', src: waveImage('') };
|
||||
|
||||
// return the filled template
|
||||
return this.fillTemplate('day', fill);
|
||||
});
|
||||
|
||||
// empty and update the container
|
||||
const dayContainer = this.elem.querySelector('.day-container');
|
||||
dayContainer.innerHTML = '';
|
||||
dayContainer.append(...days);
|
||||
this.finishDraw();
|
||||
}
|
||||
}
|
||||
|
||||
const waveImage = (conditions) => {
|
||||
const color = 'rgb(172, 165, 251)';
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 150;
|
||||
canvas.height = 20;
|
||||
const context = canvas.getContext('2d');
|
||||
context.imageSmoothingEnabled = false;
|
||||
|
||||
let y = 0;
|
||||
let r = 35;
|
||||
let arc1 = Math.PI * 0.3;
|
||||
let arc2 = Math.PI * 0.7;
|
||||
|
||||
switch (conditions) {
|
||||
case 'CHOPPY':
|
||||
y = -10;
|
||||
arc1 = Math.PI * 0.2;
|
||||
arc2 = Math.PI * 0.8;
|
||||
r = 25;
|
||||
break;
|
||||
|
||||
case 'ROUGH':
|
||||
y = -5;
|
||||
arc1 = Math.PI * 0.1;
|
||||
arc2 = Math.PI * 0.9;
|
||||
r = 20;
|
||||
break;
|
||||
|
||||
case 'LIGHT':
|
||||
default:
|
||||
y = -20;
|
||||
arc1 = Math.PI * 0.3;
|
||||
arc2 = Math.PI * 0.7;
|
||||
r = 35;
|
||||
break;
|
||||
}
|
||||
|
||||
context.beginPath();
|
||||
context.arc(35, y, r, arc1, arc2);
|
||||
context.strokeStyle = color;
|
||||
context.lineWidth = 4;
|
||||
context.stroke();
|
||||
context.beginPath();
|
||||
context.arc(75, y, r, arc1, arc2);
|
||||
context.stroke();
|
||||
context.beginPath();
|
||||
context.arc(115, y, r, arc1, arc2);
|
||||
context.stroke();
|
||||
|
||||
return canvas.toDataURL();
|
||||
};
|
||||
|
||||
// register display
|
||||
registerDisplay(new MarineForecast(11, 'marine-forecast'));
|
||||
Reference in New Issue
Block a user