feat: Add weather phenomenon decoding to METAR parser

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-02-14 15:15:13 -07:00
parent 396f609283
commit cc3c41ff2e
+60
View File
@@ -89,6 +89,66 @@
return `${code}: Visibility ${vis} statute miles`;
}
function decodeWeather(code) {
const originalCode = code;
const intensityMap = {
'-': 'Light ',
'+': 'Heavy '
};
const descriptorMap = {
'MI': 'Shallow ', 'PR': 'Partial ', 'BC': 'Patches of ', 'DR': 'Low drifting ',
'BL': 'Blowing ', 'SH': 'Showers of ', 'TS': 'Thunderstorm with ', 'FZ': 'Freezing '
};
const weatherMap = {
'DZ': 'drizzle', 'RA': 'rain', 'SN': 'snow', 'SG': 'snow grains',
'IC': 'ice crystals', 'PL': 'ice pellets', 'GR': 'hail', 'GS': 'small hail and/or snow pellets',
'UP': 'unknown precipitation', 'BR': 'mist', 'FG': 'fog', 'FU': 'smoke',
'VA': 'volcanic ash', 'DU': 'widespread dust', 'SA': 'sand', 'HZ': 'haze',
'PY': 'spray', 'PO': 'well-developed dust/sand whirls', 'SQ': 'squalls',
'FC': 'funnel cloud(s)', 'SS': 'sandstorm', 'DS': 'duststorm'
};
const precipitationTypes = ['DZ', 'RA', 'SN', 'SG', 'IC', 'PL', 'GR', 'GS', 'UP'];
let decoding = '';
let codeToParse = code;
if (codeToParse.startsWith('-') || codeToParse.startsWith('+')) {
decoding += intensityMap[codeToParse[0]];
codeToParse = codeToParse.substring(1);
}
let vicinity = '';
if (codeToParse.startsWith('VC')) {
vicinity = ' in the vicinity';
codeToParse = codeToParse.substring(2);
}
const chunks = codeToParse.match(/.{1,2}/g) || [];
let decodedChunks = [];
let hasPrecipitation = false;
chunks.forEach(chunk => {
if (descriptorMap[chunk]) {
decodedChunks.push(descriptorMap[chunk]);
} else if (weatherMap[chunk]) {
decodedChunks.push(weatherMap[chunk]);
} else {
decodedChunks.push(`unknown (${chunk})`);
}
if (precipitationTypes.includes(chunk)) {
hasPrecipitation = true;
}
});
if ((codeToParse.includes('TS') || codeToParse.includes('SH')) && !hasPrecipitation) {
decodedChunks.push('rain');
}
decoding += decodedChunks.join('');
return `${originalCode}: ${decoding.trim()}${vicinity}`;
}
function decodeClouds(code) {
const coverMap = {
'SKC': 'Sky clear',