diff --git a/metar.html b/metar.html index e35bba7..3bbc3b5 100644 --- a/metar.html +++ b/metar.html @@ -310,6 +310,42 @@ 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) { const pressure = parseInt(code.substring(3)); const hpa = (pressure < 500 ? 1000 : 900) + (pressure / 10); @@ -701,6 +737,8 @@ sections.push({ raw: part, decoded: decodeTempDew(part) }); } else if (part.startsWith('A') && part.length === 5 && !isNaN(part.substring(1))) { sections.push({ raw: part, decoded: decodeAltimeter(part) }); + } else if (part.match(/^R\d{2}[LRC]?\//)) { + sections.push({ raw: part, decoded: decodeRunwayInfo(part) }); } else { console.log(`Unknown main METAR part: ${part} in METAR: ${metarString}`); sections.push({ raw: part, decoded: `${part}: Unknown METAR component` });