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