feat: Implement METAR runway visual range (RVR) decoding
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
+38
@@ -310,6 +310,42 @@
|
|||||||
return `${code}: Altimeter ${alt.slice(0, 2)}.${alt.slice(2)} inches of mercury`;
|
return `${code}: Altimeter ${alt.slice(0, 2)}.${alt.slice(2)} inches of mercury`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function decodeRunwayInfo(code) {
|
||||||
|
const parts = code.split('/');
|
||||||
|
const runway = `Runway ${parts[0].substring(1)}`;
|
||||||
|
|
||||||
|
const visPart = parts[1];
|
||||||
|
let visText;
|
||||||
|
|
||||||
|
function decodeVis(visStr) {
|
||||||
|
if (visStr.startsWith('P')) return `greater than ${visStr.substring(1)}`;
|
||||||
|
if (visStr.startsWith('M')) return `less than ${visStr.substring(1)}`;
|
||||||
|
return visStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (visPart.includes('V')) {
|
||||||
|
const [minVis, maxVis] = visPart.replace('FT', '').split('V');
|
||||||
|
visText = `visual range variable between ${decodeVis(minVis)} and ${decodeVis(maxVis)} feet`;
|
||||||
|
} else {
|
||||||
|
const vis = visPart.replace('FT', '');
|
||||||
|
visText = `visual range ${decodeVis(vis)} feet`;
|
||||||
|
}
|
||||||
|
|
||||||
|
let trendText = '';
|
||||||
|
if (parts.length > 2 && parts[2]) {
|
||||||
|
const trendCode = parts[2];
|
||||||
|
const trendMap = {
|
||||||
|
'N': 'not significant',
|
||||||
|
'U': 'upward',
|
||||||
|
'D': 'downward'
|
||||||
|
};
|
||||||
|
const trendDesc = trendMap[trendCode] || 'unknown';
|
||||||
|
trendText = `, trend ${trendDesc} (${trendCode})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${code}: ${runway} ${visText}${trendText}`;
|
||||||
|
}
|
||||||
|
|
||||||
function decodeSlp(code) {
|
function decodeSlp(code) {
|
||||||
const pressure = parseInt(code.substring(3));
|
const pressure = parseInt(code.substring(3));
|
||||||
const hpa = (pressure < 500 ? 1000 : 900) + (pressure / 10);
|
const hpa = (pressure < 500 ? 1000 : 900) + (pressure / 10);
|
||||||
@@ -701,6 +737,8 @@
|
|||||||
sections.push({ raw: part, decoded: decodeTempDew(part) });
|
sections.push({ raw: part, decoded: decodeTempDew(part) });
|
||||||
} else if (part.startsWith('A') && part.length === 5 && !isNaN(part.substring(1))) {
|
} else if (part.startsWith('A') && part.length === 5 && !isNaN(part.substring(1))) {
|
||||||
sections.push({ raw: part, decoded: decodeAltimeter(part) });
|
sections.push({ raw: part, decoded: decodeAltimeter(part) });
|
||||||
|
} else if (part.match(/^R\d{2}[LRC]?\//)) {
|
||||||
|
sections.push({ raw: part, decoded: decodeRunwayInfo(part) });
|
||||||
} else {
|
} else {
|
||||||
console.log(`Unknown main METAR part: ${part} in METAR: ${metarString}`);
|
console.log(`Unknown main METAR part: ${part} in METAR: ${metarString}`);
|
||||||
sections.push({ raw: part, decoded: `${part}: Unknown METAR component` });
|
sections.push({ raw: part, decoded: `${part}: Unknown METAR component` });
|
||||||
|
|||||||
Reference in New Issue
Block a user