diff --git a/index.html b/index.html index ee40981..661e4c3 100644 --- a/index.html +++ b/index.html @@ -222,6 +222,7 @@

Stage

+
@@ -261,6 +262,7 @@

Stage

+ diff --git a/static/js/file_upload.js b/static/js/file_upload.js index 175e5c3..f644742 100644 --- a/static/js/file_upload.js +++ b/static/js/file_upload.js @@ -9,6 +9,8 @@ function mapFromFile(data, type, accessible) { parsed = parseIbtracs(data); } else if (type === "rsmc") { parsed = parseRsmc(data); + } else if (type === "storms") { + parsed = parseStorms(data) } else { return; } diff --git a/static/js/storms.js b/static/js/storms.js new file mode 100644 index 0000000..3c9a63a --- /dev/null +++ b/static/js/storms.js @@ -0,0 +1,60 @@ +const WIND_SPEED_THRESHOLDS = { + TD: 34, + TS: 64, + C1: 83, + C2: 96, + C3: 113, + C4: 137 +}; +const MS_TO_KNOTS = 1.943844; + +function windSpeedToCategory(speed) { + const knots = speed * MS_TO_KNOTS; + + for (const [category, threshold] of Object.entries(WIND_SPEED_THRESHOLDS)) { + if (knots < threshold) return category; + } + return 'C5'; +} + +function getStormsShape(category) { + if (['TD', 'TS'].includes(category) || category.startsWith('C')) { + return 'circle'; + } + console.error("Unknown STORMS category shape: " + category); + return 'triangle'; +} + +function formatLatitude(lat) { + return `${Math.abs(lat).toFixed(1)}${lat < 0 ? 'S' : 'N'}`; +} + +function formatLongitude(lon) { + const adjustedLon = lon > 180 ? lon - 360 : lon; + return `${Math.abs(adjustedLon).toFixed(1)}${adjustedLon < 0 ? 'W' : 'E'}`; +} + +function parseStorms(data) { + const lines = data.trim().split('\n'); + const parsed = []; + + lines.forEach(line => { + const cols = line.trim().split(/[\s,]+/).filter(col => col.length > 0); + + if (cols.length >= 13) { + const tcNumber = cols[2].padStart(2, '0'); + const windSpeedKnots = parseFloat(cols[8]) * MS_TO_KNOTS; + const category = windSpeedToCategory(parseFloat(cols[9])); + + parsed.push({ + name: tcNumber, + shape: getStormsShape(category), + category: speedToCat(windSpeedKnots), + latitude: formatLatitude(parseFloat(cols[5])), + longitude: formatLongitude(parseFloat(cols[6])), + }); + } + }); + + return parsed; +} \ No newline at end of file