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` });