Add fog derived hazards, start of work for 0.1.1
This commit is contained in:
parent
587c9d4d62
commit
d917bba357
3 changed files with 45 additions and 7 deletions
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "ws4kp-linhanced",
|
"name": "ws4kp-linhanced",
|
||||||
"version": "0.1",
|
"version": "0.1.1",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "ws4kp-linhanced",
|
"name": "ws4kp-linhanced",
|
||||||
"version": "0.1",
|
"version": "0.1.1",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dotenv": "^17.0.1",
|
"dotenv": "^17.0.1",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "ws4kp-linhanced",
|
"name": "ws4kp-linhanced",
|
||||||
"version": "0.1",
|
"version": "0.1.1",
|
||||||
"description": "WeatherStar 4000+: Linhanced - A Linux-focused fork of the WeatherStar 4000+ project",
|
"description": "WeatherStar 4000+: Linhanced - A Linux-focused fork of the WeatherStar 4000+ project",
|
||||||
"main": "index.mjs",
|
"main": "index.mjs",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,9 @@ const SEVERITY_RANK = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const RULE_PRIORITY = {
|
const RULE_PRIORITY = {
|
||||||
tropical: 6,
|
tropical: 7,
|
||||||
thunderstorm: 5,
|
thunderstorm: 6,
|
||||||
|
fog: 5,
|
||||||
freezing: 4,
|
freezing: 4,
|
||||||
snow: 3,
|
snow: 3,
|
||||||
rain: 2,
|
rain: 2,
|
||||||
|
|
@ -23,11 +24,13 @@ const WEATHER_CODES = {
|
||||||
snow: new Set([71, 73, 75, 77, 85, 86]),
|
snow: new Set([71, 73, 75, 77, 85, 86]),
|
||||||
thunderstorm: new Set([95, 96, 99]),
|
thunderstorm: new Set([95, 96, 99]),
|
||||||
rain: new Set([51, 53, 55, 61, 63, 65, 80, 81, 82]),
|
rain: new Set([51, 53, 55, 61, 63, 65, 80, 81, 82]),
|
||||||
|
fog: new Set([45, 48]),
|
||||||
};
|
};
|
||||||
|
|
||||||
const thresholds = {
|
const thresholds = {
|
||||||
lowVisibilitySevere: 5 * METERS_PER_MILE,
|
lowVisibilitySevere: 5 * METERS_PER_MILE,
|
||||||
lowVisibilityExtreme: 2 * METERS_PER_MILE,
|
lowVisibilityExtreme: 2 * METERS_PER_MILE,
|
||||||
|
denseFogVisibility: 1000,
|
||||||
gustSevere: 20 * KPH_PER_MPH,
|
gustSevere: 20 * KPH_PER_MPH,
|
||||||
gustExtreme: 35 * KPH_PER_MPH,
|
gustExtreme: 35 * KPH_PER_MPH,
|
||||||
highWindSevere: 40 * KPH_PER_MPH,
|
highWindSevere: 40 * KPH_PER_MPH,
|
||||||
|
|
@ -85,15 +88,22 @@ const getWorstHour = (hours, evaluator) => hours.reduce((worst, hour) => {
|
||||||
const evaluateThunderstorm = (hours) => getWorstHour(hours, (hour) => {
|
const evaluateThunderstorm = (hours) => getWorstHour(hours, (hour) => {
|
||||||
const code = Number(hour.weather_code ?? 0);
|
const code = Number(hour.weather_code ?? 0);
|
||||||
if (!WEATHER_CODES.thunderstorm.has(code)) return null;
|
if (!WEATHER_CODES.thunderstorm.has(code)) return null;
|
||||||
|
const visibility = hour.visibility ?? Number.POSITIVE_INFINITY;
|
||||||
|
const lowVisibility = visibility < thresholds.lowVisibilitySevere;
|
||||||
|
|
||||||
if (code === 96 || code === 99) {
|
if (code === 96 || code === 99) {
|
||||||
return {
|
return {
|
||||||
severity: 'Extreme',
|
severity: 'Extreme',
|
||||||
description: 'Thunderstorms with hail are possible in the next several hours and may create dangerous outdoor conditions.',
|
description: lowVisibility
|
||||||
|
? 'Thunderstorms with hail and very low visibility are expected in the next several hours and may create dangerous outdoor and travel conditions.'
|
||||||
|
: 'Thunderstorms with hail are possible in the next several hours and may create dangerous outdoor conditions.',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
severity: 'Severe',
|
severity: 'Severe',
|
||||||
description: 'Thunderstorms are possible in the next several hours and may create hazardous outdoor conditions.',
|
description: lowVisibility
|
||||||
|
? 'Thunderstorms with reduced visibility are expected in the next several hours and may create hazardous outdoor and travel conditions.'
|
||||||
|
: 'Thunderstorms are possible in the next several hours and may create hazardous outdoor conditions.',
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -204,11 +214,34 @@ const evaluateWind = (hours) => getWorstHour(hours, (hour) => {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const evaluateFog = (hours) => getWorstHour(hours, (hour) => {
|
||||||
|
const code = Number(hour.weather_code ?? 0);
|
||||||
|
if (!WEATHER_CODES.fog.has(code)) return null;
|
||||||
|
const visibility = hour.visibility ?? Number.POSITIVE_INFINITY;
|
||||||
|
|
||||||
|
if (visibility <= thresholds.denseFogVisibility) {
|
||||||
|
return {
|
||||||
|
severity: 'Extreme',
|
||||||
|
description: 'Dense fog with very low visibility is expected in the next several hours and may create dangerous travel conditions.',
|
||||||
|
event: 'Dense Fog Warning',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (visibility < thresholds.lowVisibilitySevere) {
|
||||||
|
return {
|
||||||
|
severity: 'Severe',
|
||||||
|
description: 'Reduced visibility with mist or low cloud is expected in the next several hours and may create hazardous travel conditions.',
|
||||||
|
event: 'Reduced Visibility Advisory',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
const deriveHazards = (weatherParameters) => {
|
const deriveHazards = (weatherParameters) => {
|
||||||
const upcomingHours = getUpcomingHours(weatherParameters);
|
const upcomingHours = getUpcomingHours(weatherParameters);
|
||||||
if (upcomingHours.length === 0) return [];
|
if (upcomingHours.length === 0) return [];
|
||||||
const tropicalCandidate = evaluateTropical(upcomingHours);
|
const tropicalCandidate = evaluateTropical(upcomingHours);
|
||||||
const thunderstormCandidate = evaluateThunderstorm(upcomingHours);
|
const thunderstormCandidate = evaluateThunderstorm(upcomingHours);
|
||||||
|
const fogCandidate = evaluateFog(upcomingHours);
|
||||||
const freezingCandidate = evaluateFreezing(upcomingHours);
|
const freezingCandidate = evaluateFreezing(upcomingHours);
|
||||||
const snowCandidate = evaluateSnow(upcomingHours);
|
const snowCandidate = evaluateSnow(upcomingHours);
|
||||||
const rainCandidate = evaluateRain(upcomingHours);
|
const rainCandidate = evaluateRain(upcomingHours);
|
||||||
|
|
@ -226,6 +259,11 @@ const deriveHazards = (weatherParameters) => {
|
||||||
priority: RULE_PRIORITY.thunderstorm,
|
priority: RULE_PRIORITY.thunderstorm,
|
||||||
...thunderstormCandidate,
|
...thunderstormCandidate,
|
||||||
}),
|
}),
|
||||||
|
fogCandidate && buildDerivedHazard({
|
||||||
|
id: 'derived-severe-weather-alert-fog',
|
||||||
|
priority: RULE_PRIORITY.fog,
|
||||||
|
...fogCandidate,
|
||||||
|
}),
|
||||||
freezingCandidate && buildDerivedHazard({
|
freezingCandidate && buildDerivedHazard({
|
||||||
id: 'derived-severe-weather-alert-freezing',
|
id: 'derived-severe-weather-alert-freezing',
|
||||||
priority: RULE_PRIORITY.freezing,
|
priority: RULE_PRIORITY.freezing,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue