From c95438e650e47c7b90c027a761698439459bede3 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 16:26:59 -0500 Subject: [PATCH 01/19] Update README.md --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 9d5d759..2943963 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ This package can be installed using a simple `npm install` command ``` npm install hurdatparser ``` +You can import it into your project using `import` +``` +import { Hurdat, Util, Point } from "hurdatparser" +``` ## [Documentation](https://github.com/wilburcoding/hurdatparser/tree/main/docs) # Contributing From 98f3aaaa7ad73c86c4225cbdca26815113b6b11c Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 16:51:32 -0500 Subject: [PATCH 02/19] Update util.md --- docs/util.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/docs/util.md b/docs/util.md index 6fe1f32..fa79a22 100644 --- a/docs/util.md +++ b/docs/util.md @@ -55,6 +55,32 @@ Convert 50 kt to mph util.ktToMph(50); ``` +## `Util.coordDist(point1, point2, unit)` + +Get distance between 2 coordinates + +#### Parameters + +`point1` - First point to calculate distance between +`point2` - Second point to calculate distance between +`unit` (Optional) - Specify unit for result. km" for kilometers and "mi" for miles. Default value is "km" + +#### Returns + +Distance between provided coordinates + +#### Example usage + +Calculate the distance between (59, 14) and (60, 14) in miles +```javascript +console.log(util.coordDist(new Point(59, 13), new Point(60, 14), "mi")) +``` + +Calculate the distance between (58, 5) and (59, 8) in kilometers +```javascript +console.log(util.coordDist(new Point(58, 5), new Point(59, 8))) +``` + ## `Util.ktToKph(kt)` Convert knots to kph From 4e070d52d826a78dff20f47261afb2552aab2ebd Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 16:52:18 -0500 Subject: [PATCH 03/19] Add coordDist() function for Util --- src/index.js | 61 ++++++++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/src/index.js b/src/index.js index 919fd4e..93dbe94 100644 --- a/src/index.js +++ b/src/index.js @@ -32,7 +32,7 @@ class Hurdat { var stormdata = [] var stormheader = "" for (var item of raw) { - if (item.substring(0, 2) == "AL" || item.substring(0,2)=="EP" || item.substring(0,2)=="CP") { + if (item.substring(0, 2) == "AL" || item.substring(0, 2) == "EP" || item.substring(0, 2) == "CP") { // if (stormheader != "") { self.storms.push(new Storm(stormheader, stormdata)) @@ -119,10 +119,10 @@ class Hurdat { } } if (Object.keys(query).includes("date")) { - if (query["date"].length==2 && query["date"][0] instanceof Date && query["date"][1] instanceof Date) { + if (query["date"].length == 2 && query["date"][0] instanceof Date && query["date"][1] instanceof Date) { //will be fixed - matches = matches && (query["date"][0].getTime() <= storm.formed.getTime() && query["date"][1].getTime() >= storm.dissipated.getTime()) + matches = matches && (query["date"][0].getTime() <= storm.formed.getTime() && query["date"][1].getTime() >= storm.dissipated.getTime()) } else { throw new Error("Query values for date must be date opjects") } @@ -273,27 +273,27 @@ class Entry { } class Util { constructor() { } - download(filename,source) { - if (source==="natl") { - axios.get('https://www.nhc.noaa.gov/data/hurdat/hurdat2-1851-2021-100522.txt').then(function(response) { - const text = response.data; + download(filename, source) { + if (source === "natl") { + axios.get('https://www.nhc.noaa.gov/data/hurdat/hurdat2-1851-2021-100522.txt').then(function(response) { + const text = response.data; - fs.writeFile(filename, text, function(err) { - if (err) { - throw new Error("Error saving file") - } + fs.writeFile(filename, text, function(err) { + if (err) { + throw new Error("Error saving file") + } + }); }); - }); - } else if (source==="pac") { + } else if (source === "pac") { axios.get('https://www.nhc.noaa.gov/data/hurdat/hurdat2-nepac-1949-2021-091522.txt').then(function(response) { - const text = response.data; + const text = response.data; - fs.writeFile(filename, text, function(err) { - if (err) { - throw new Error("Error saving file") - } + fs.writeFile(filename, text, function(err) { + if (err) { + throw new Error("Error saving file") + } + }); }); - }); } else { throw new Error("Invalid data type. Source must be \"natl\" (North Atlantic) or \"pac\" (Eastern and Central Pacific)") } @@ -340,13 +340,28 @@ class Util { } throw new Error("Invalid Parameter (Parameter needs to be a Point)") } - inside(minlat,maxlat,minlong,maxlong,point) { + inside(minlat, maxlat, minlong, maxlong, point) { if (Number(minlat) == minlat && Number(maxlat) == maxlat && Number(minlong) == minlong && Number(maxlong) == maxlong && point instanceof Point) { - return (point.getLat() >= minlat && point.getLat() <= maxlat && point.getLong() >= minlong && point.getLong() <= maxlong) - } + return (point.getLat() >= minlat && point.getLat() <= maxlat && point.getLong() >= minlong && point.getLong() <= maxlong) + } throw new Error("Invalid parameters. minlat, maxlat, minlong, and maxlong need to be of type Number, point needs to be of type Point") } - + coordDist(point1, point2, unit="km") { + //uses haversine formula + //https://www.htmlgoodies.com/javascript/calculate-the-distance-between-two-points-in-your-web-apps/ + //https://stackoverflow.com/questions/18883601/function-to-calculate-distance-between-two-coordinates + var radlat1 = Math.PI * point1.getLat() / 180; + var radlat2 = Math.PI * point2.getLat() / 180; + var theta = point1.getLong() - point2.getLong() + var radtheta = Math.PI * theta / 180 + var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); + dist = Math.acos(dist) * 180 / Math.PI * 60 * 1.1515 + if (unit == "km") { dist = dist * 1.609344 } + if (unit == "mi") { dist = dist * 0.8684 } + return dist + + } + } export { From e1806021e078ea824af3a4363f45270e9bb2fe19 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:32:23 -0500 Subject: [PATCH 04/19] Add distance property to Storm --- src/index.js | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 93dbe94..a2f7563 100644 --- a/src/index.js +++ b/src/index.js @@ -220,9 +220,26 @@ class Storm { this.peakpressure = lastentry } } + this.formed = this.entries[0].date this.dissipated = this.entries[this.entries.length - 1].date + var distkm = 0; + var distmi = 0; + for (var i = 0; i < this.entries.length - 1; i++) { + var radlat1 = Math.PI * this.entries[i].point.getLat() / 180; + var radlat2 = Math.PI * this.entries[i+1].point.getLat() / 180; + var theta = this.entries[i].point.getLong() - this.entries[i+1].point.getLong() + var radtheta = Math.PI * theta / 180 + var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); + dist = Math.acos(dist) * 180 / Math.PI * 60 * 1.1515 + distkm+=dist * 1.609344 + distmi+=dist * 0.8684 + } + this.distance = { + "mi":distmi, + "km":distkm + } } catch (e) { console.log(e) throw new Error("An error record while parsing storm data") @@ -346,7 +363,7 @@ class Util { } throw new Error("Invalid parameters. minlat, maxlat, minlong, and maxlong need to be of type Number, point needs to be of type Point") } - coordDist(point1, point2, unit="km") { + coordDist(point1, point2, unit = "km") { //uses haversine formula //https://www.htmlgoodies.com/javascript/calculate-the-distance-between-two-points-in-your-web-apps/ //https://stackoverflow.com/questions/18883601/function-to-calculate-distance-between-two-coordinates From d85f00a7d2b39903868bc92621ed1725804cb7e5 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:35:59 -0500 Subject: [PATCH 05/19] Add distancekm and distancemi query fields With addition of distance property in Storm --- src/index.js | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index a2f7563..83ed217 100644 --- a/src/index.js +++ b/src/index.js @@ -141,6 +141,35 @@ class Hurdat { throw new Error("Query value for landfallnum must be Number or an array with 2 elements, a minimum and a maximum") } } + if (Object.keys(query).includes("distancekm")) { + if (Number(query["distancekm"]) == query["distancekm"]) { + //is number + matches = matches && storm.distance.km == query["distancekm"] + } else if (query["distancekm"].constructor === Array) { + if (query["distancekm"].length == 2 && query["distancekm"][1] >= query["distancekm"][0]) { + matches = matches && (storm.distance.km >= query["distancekm"][0] && storm.distance.km <= query["distancekm"][1]) + } else { + throw new Error("Invalid array range provided. Parameter should be an array with 2 elements of type Number, a minimum and a maximum") + } + } else { + throw new Error("Query value for distancekm must be Number or an array with 2 elements, a minimum and a maximum") + } + } + //merge with distancekm possible in future + if (Object.keys(query).includes("distancemi")) { + if (Number(query["distancemi"]) == query["distancemi"]) { + //is number + matches = matches && storm.distance.mi == query["distancemi"] + } else if (query["distancemi"].constructor === Array) { + if (query["distancemi"].length == 2 && query["distancemi"][1] >= query["distancemi"][0]) { + matches = matches && (storm.distance.mi >= query["distancemi"][0] && storm.distance.mi <= query["distancemi"][1]) + } else { + throw new Error("Invalid array range provided. Parameter should be an array with 2 elements of type Number, a minimum and a maximum") + } + } else { + throw new Error("Query value for distancemi must be Number or an array with 2 elements, a minimum and a maximum") + } + } if (Object.keys(query).includes("point")) { if (query["point"].constructor === Array) { if (query["point"].length == 4 && query["point"][1] >= query["point"][0] && query["point"][3] >= query["point"][2]) { @@ -237,8 +266,8 @@ class Storm { distmi+=dist * 0.8684 } this.distance = { - "mi":distmi, - "km":distkm + mi:distmi, + km:distkm } } catch (e) { console.log(e) From 554ff59a7ff91c5812f4e9215128a7045dadbde0 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:38:59 -0500 Subject: [PATCH 06/19] Add distancekm and distancemi fields to hurdat.md --- docs/hurdat.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/hurdat.md b/docs/hurdat.md index a167d5a..40ce17f 100644 --- a/docs/hurdat.md +++ b/docs/hurdat.md @@ -64,13 +64,15 @@ A method to quickly query for storms - `season` (Number) - Look for storms in a certain year - `namematch` (Regular expression) - Look for storms with names matching a certain regular expression - `number` (Number or Array of numbers) - Look for storms whose number is equal to the provided number or is in the provided array -- `peakwind` (Number or Array of numbers) - Look for storms whose highest wind speed (kt) is equal to the provided number or is greater than or equal to the first item of the provided array (minimum) and less than or equal to the second item of the provided array (maximum) -- `peakpressure` (Number or Array of numbers) - Look for storms whose lowest pressure (mb) is equal to the provided number or is greater than or equal to the first item of the provided array (minimum) and less than or equal to the second item of the provided array (maximum) +- `peakwind` (Number or Array of 2 numbers) - Look for storms whose highest wind speed (kt) is equal to the provided number or is greater than or equal to the first item of the provided array (minimum) and less than or equal to the second item of the provided array (maximum) +- `peakpressure` (Number or Array of 2 numbers) - Look for storms whose lowest pressure (mb) is equal to the provided number or is greater than or equal to the first item of the provided array (minimum) and less than or equal to the second item of the provided array (maximum) - `date` (Array of 2 Date objects) - Look for storms that were active during period of time in the provided array - **Note**: This feature is currently experimental and could lead to inaccurate results -- `landfallnum` (Number or Array of numbers) - Look for storms whose number of landfalls is equal to the provided number or is greater than or equal to the first item of the provided array (beginning of date range) and less than or equal to the second item of the provided array (ending of date range) +- `landfallnum` (Number or Array of 2 numbers) - Look for storms whose number of landfalls is equal to the provided number or is greater than or equal to the first item of the provided array (beginning of date range) and less than or equal to the second item of the provided array (ending of date range) - `point` (Array of 4 numbers) - Look for storms that have passed through an area (Item 1 of the provided array is the minimum latitude, Item 2 is the maximum latitude, Item 3 is the minimum longitude, Item 4 is the maximum longitude) - `landfall` (Array of 4 numbers) - Look for storms that have made landfall in an area (Item 1 of the provided array is the minimum latitude, Item 2 is the maximum latitude, Item 3 is the minimum longitude, Item 4 is the maximum longitude) +- `distancekm` (Number or Array of 2 numbers) - Look for storms whose track distance in kilometers is equal to the provided number or is greater than or equal to the first item of the provided array (beginning of range) and less than or equal to the second item of the provided array (ending of range) +- `distancemi` (Number or Array of 2 numbers) - Look for storms whose track distance in miles is equal to the provided number or is greater than or equal to the first item of the provided array (beginning of range) and less than or equal to the second item of the provided array (ending of range) #### Returns From 04b030502e463bd1dda15695665232094bdcf2a2 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:41:40 -0500 Subject: [PATCH 07/19] Add additional example with distancemi --- docs/hurdat.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/hurdat.md b/docs/hurdat.md index 40ce17f..52a8472 100644 --- a/docs/hurdat.md +++ b/docs/hurdat.md @@ -89,7 +89,7 @@ hurdat.filter({"season" : "2005","landfallnum" : [3, 5]}); Find storms that made landfall on Long Island before 1950 ```javascript -hurdat.filter({"date" : [new Date(1800, 1, 1), new Date(1950, 1, 1)], "landfall" : [40.54, 41.21, -71.75, -74.18]}); +hurdat.filter({"date" : [new Date(1800, 0, 1), new Date(1950, 0, 1)], "landfall" : [40.54, 41.21, -71.75, -74.18]}); ``` Find storms that made at least `5` landfalls and no more than `10` landfalls that had a peak intensity of `80` to `100` knots @@ -97,3 +97,9 @@ Find storms that made at least `5` landfalls and no more than `10` landfalls tha ```javascript hurdat.filter({"peakwind": [80, 100], "landfallnum": [5, 10]}) ``` + +Find storms that have a track distance of at least 2,500 miles and less than or equal to 10,000 miles after 2000 + +```javascript +hurdat.filter({"distancemi": [2500, 10000], "date": [new Date(2000, 0, 1), new Date(2500, 0, 1)]}) +``` From 19462e7b99b5e32003d7d3ff0dc08c873db386e3 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:47:19 -0500 Subject: [PATCH 08/19] Add error handling for file loading --- src/index.js | 53 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 26 deletions(-) diff --git a/src/index.js b/src/index.js index 83ed217..ae3c04d 100644 --- a/src/index.js +++ b/src/index.js @@ -2,7 +2,6 @@ import axios from 'axios'; import * as fs from 'fs'; class Point { constructor(lat, long) { - if (lat < -90 || lat > 90 || Number(lat) != lat) { throw new Error("Parameter latitude must be a Number in range -90 and 90") } @@ -24,28 +23,30 @@ class Point { } class Hurdat { constructor(filename) { - var self = this - var data = fs.readFileSync(filename, 'utf8') - //if (err) throw new Error("Unable to load file"); - var raw = data.split("\n"); - self.storms = [] - var stormdata = [] - var stormheader = "" - for (var item of raw) { - if (item.substring(0, 2) == "AL" || item.substring(0, 2) == "EP" || item.substring(0, 2) == "CP") { - // - if (stormheader != "") { - self.storms.push(new Storm(stormheader, stormdata)) - stormdata = [] - } - stormheader = item + try { + var self = this + var data = fs.readFileSync(filename, 'utf8') + var raw = data.split("\n"); + self.storms = [] + var stormdata = [] + var stormheader = "" + for (var item of raw) { + if (item.substring(0, 2) == "AL" || item.substring(0, 2) == "EP" || item.substring(0, 2) == "CP") { + if (stormheader != "") { + self.storms.push(new Storm(stormheader, stormdata)) + stormdata = [] + } + stormheader = item - } else { - stormdata.push(item) + } else { + stormdata.push(item) + } } + } catch (e) { + // Catch error + console.error(e) + throw new Error("Unable to parse data file. File may be invalid") } - - } funcFilter(func) { try { @@ -257,17 +258,17 @@ class Storm { for (var i = 0; i < this.entries.length - 1; i++) { var radlat1 = Math.PI * this.entries[i].point.getLat() / 180; - var radlat2 = Math.PI * this.entries[i+1].point.getLat() / 180; - var theta = this.entries[i].point.getLong() - this.entries[i+1].point.getLong() + var radlat2 = Math.PI * this.entries[i + 1].point.getLat() / 180; + var theta = this.entries[i].point.getLong() - this.entries[i + 1].point.getLong() var radtheta = Math.PI * theta / 180 var dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta); dist = Math.acos(dist) * 180 / Math.PI * 60 * 1.1515 - distkm+=dist * 1.609344 - distmi+=dist * 0.8684 + distkm += dist * 1.609344 + distmi += dist * 0.8684 } this.distance = { - mi:distmi, - km:distkm + mi: distmi, + km: distkm } } catch (e) { console.log(e) From 98ce542cf2620876738f1a02bcc312c14a98d60d Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 17:54:07 -0500 Subject: [PATCH 09/19] Cleanup entry parsing --- src/index.js | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/index.js b/src/index.js index ae3c04d..c44f739 100644 --- a/src/index.js +++ b/src/index.js @@ -55,7 +55,7 @@ class Hurdat { } throw new Error("Parameter must be a function") } catch (e) { - console.log(e) + console.error(e) throw new Error("Error filtering items") } } @@ -66,9 +66,7 @@ class Hurdat { var matches = true; if (Object.keys(query).includes("season")) { if (Number(query["season"]) == query["season"]) { - //is number matches = matches && storm.year == query["season"] - } else { throw new Error("Query value for season must be number") } @@ -197,10 +195,8 @@ class Hurdat { for (var item of storm.entries) { var point = item.point if (point.getLat() >= query["landfall"][0] && point.getLat() <= query["landfall"][1] && point.getLong() >= query["landfall"][2] && point.getLong() <= query["landfall"][3] && item.identifier == "L") { - isin = true; break - } } matches = matches && isin @@ -232,7 +228,6 @@ class Storm { var id = data[0].trim() this.id = id this.peakwind = null - this.peakpressure = null this.number = parseInt(id.substring(2, 4)) this.year = parseInt(id.substring(4, 9)) @@ -290,26 +285,35 @@ class Entry { this.point = new Point((data[4][data[4].length - 1] == "N" ? parseFloat(data[4].substring(0, data[4].length - 1)) : parseFloat(data[4].substring(0, data[4].length - 1)) * -1), (data[5][data[5].length - 1] == "E" ? parseFloat(data[5].substring(0, data[5].length - 1)) : parseFloat(data[5].substring(0, data[5].length - 1)) * -1)) this.wind = (data[6].trim() != "" ? parseInt(data[6].trim()) : null) this.pressure = parseInt(data[7].trim()) + for (var i = 0; i < data.length; i++) { + if (data[i] == -999 || data[i] == -99) { + data[i]=null; + } else { + if (i >= 8 && i <= 20) { + data[i]=parseInt(data[i]) + } + } + } this.radius = { "34": { - "NE": (data[8].trim() != "-999" ? parseInt(data[8].trim()) : null), - "SE": (data[9].trim() != "-999" ? parseInt(data[9].trim()) : null), - "SW": (data[10].trim() != "-999" ? parseInt(data[10].trim()) : null), - "NW": (data[11].trim() != "-999" ? parseInt(data[11].trim()) : null) + "NE": data[8], + "SE": data[9], + "SW": data[10], + "NW": data[11] }, "50": { - "NE": (data[12].trim() != "-999" ? parseInt(data[12].trim()) : null), - "SE": (data[13].trim() != "-999" ? parseInt(data[13].trim()) : null), - "SW": (data[14].trim() != "-999" ? parseInt(data[14].trim()) : null), - "NW": (data[15].trim() != "-999" ? parseInt(data[15].trim()) : null) + "NE": data[12], + "SE": data[13], + "SW": data[14], + "NW": data[15] }, "64": { - "NE": (data[16].trim() != "-999" ? parseInt(data[16].trim()) : null), - "SE": (data[17].trim() != "-999" ? parseInt(data[17].trim()) : null), - "SW": (data[18].trim() != "-999" ? parseInt(data[18].trim()) : null), - "NW": (data[19].trim() != "-999" ? parseInt(data[19].trim()) : null) + "NE": data[16], + "SE": data[17], + "SW": data[18], + "NW": data[19] }, - "max": parseInt(data[20].trim()) + "max": data[20] } } catch (e) { console.log(e) From 3b5765a8bb406b9cc8a85d9b242595b6d106ce88 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:05:07 -0500 Subject: [PATCH 10/19] Change all console.log to console.error --- src/index.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index c44f739..612e52e 100644 --- a/src/index.js +++ b/src/index.js @@ -37,7 +37,6 @@ class Hurdat { stormdata = [] } stormheader = item - } else { stormdata.push(item) } @@ -214,7 +213,7 @@ class Hurdat { throw new Error("Parameter must be of type dictionary") } } catch (e) { - console.log(e) + console.error(e); throw new Error("Invalid parameter or query") } } @@ -266,7 +265,7 @@ class Storm { km: distkm } } catch (e) { - console.log(e) + console.error(e) throw new Error("An error record while parsing storm data") } } @@ -316,7 +315,7 @@ class Entry { "max": data[20] } } catch (e) { - console.log(e) + console.error(e) throw new Error("An error record while parsing entry data") } } @@ -410,11 +409,8 @@ class Util { if (unit == "km") { dist = dist * 1.609344 } if (unit == "mi") { dist = dist * 0.8684 } return dist - } - } - export { Hurdat, Util, From 96d5f4266217222cf9beb6b201b377f5d73992ff Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:18:57 -0500 Subject: [PATCH 11/19] More efficient method of detecting storm header --- src/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 612e52e..216abc1 100644 --- a/src/index.js +++ b/src/index.js @@ -31,7 +31,7 @@ class Hurdat { var stormdata = [] var stormheader = "" for (var item of raw) { - if (item.substring(0, 2) == "AL" || item.substring(0, 2) == "EP" || item.substring(0, 2) == "CP") { + if (item.split(",").length < 4) { if (stormheader != "") { self.storms.push(new Storm(stormheader, stormdata)) stormdata = [] @@ -42,7 +42,6 @@ class Hurdat { } } } catch (e) { - // Catch error console.error(e) throw new Error("Unable to parse data file. File may be invalid") } From 5722d2751f8a512051dc1e7d3d5a078174ace0a8 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:21:19 -0500 Subject: [PATCH 12/19] Add setters for Point --- src/index.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/index.js b/src/index.js index 216abc1..2f06b5a 100644 --- a/src/index.js +++ b/src/index.js @@ -20,6 +20,18 @@ class Point { getCoord() { return [this.lat, this.long] } + setLat(newlat) { + if (newlat < -90 || newlat > 90 || Number(newlat) != newlat) { + throw new Error("Parameter latitude must be a Number in range -90 and 90") + } + this.lat = newlat; + } + setLong(newlong) { + if (newlong < -180 || newlong > 180 || Number(newlong) != newlong) { + throw new Error("Parameter latitude must be a Number in range -90 and 90") + } + this.long = newlong; + } } class Hurdat { constructor(filename) { From ad00aad3d437f5295332e39a1e911589461437e9 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:23:18 -0500 Subject: [PATCH 13/19] Merge funcfilter with filter --- src/index.js | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/index.js b/src/index.js index 2f06b5a..ab6ddca 100644 --- a/src/index.js +++ b/src/index.js @@ -58,17 +58,6 @@ class Hurdat { throw new Error("Unable to parse data file. File may be invalid") } } - funcFilter(func) { - try { - if (func instanceof Function) { - return this.storms.filter((storm) => func(storm)) - } - throw new Error("Parameter must be a function") - } catch (e) { - console.error(e) - throw new Error("Error filtering items") - } - } filter(query) { try { if (query.constructor == Object) { @@ -220,8 +209,10 @@ class Hurdat { return matches }) + } else if (func instanceof Function) { + return this.storms.filter((storm) => func(storm)) } else { - throw new Error("Parameter must be of type dictionary") + throw new Error("Filter must be a function or object with query fields") } } catch (e) { console.error(e); From 68db671e5c46dde289e9dd18f9ccab999e127f76 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:26:18 -0500 Subject: [PATCH 14/19] Update point.md to include new setters --- docs/point.md | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/docs/point.md b/docs/point.md index d9bf5ba..b71df8a 100644 --- a/docs/point.md +++ b/docs/point.md @@ -48,3 +48,34 @@ Get latitude value for Point point.getLat(); ``` +## `Util.setLat(newlat)` + +Set latitude value for Point + +#### Parameters + +`newlat` - new latitude value + +#### Example Usage + +Set latitude value for Point to 40 + +```javascript +point.setLat(40); +``` + +## `Util.setLong(newlong)` + +Set longtiude value for Point + +#### Parameters + +`newlong` - new latitude value + +#### Example Usage + +Set longitude value for Point to 57 + +```javascript +point.setLong(57); +``` From 13762131f9113c717fcea3cca77cb5be1c79d570 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:30:39 -0500 Subject: [PATCH 15/19] Update documentation to new filter function --- docs/hurdat.md | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/docs/hurdat.md b/docs/hurdat.md index 52a8472..4e3b16d 100644 --- a/docs/hurdat.md +++ b/docs/hurdat.md @@ -22,36 +22,6 @@ Initalize and load Hurdat2 data const hurdat = new Hurdat("path/to/data.txt"); ``` -## `Hurdat.funcFilter(func)` - -A method to filter storms using the passed function - -#### Parameters - -`func` - Function used to filter storms - -#### Returns - -Array of `Storm` filtered - -#### Example Usage - -Finds storms named "Henri" - -```javascript -hurdat.funcFilter(function(storm) { - return storm.name == "Henri"; -}); -``` - -Find storms with forming in July - -```javascript -hurdat.funcFilter(function(storm) { - return storm.formed.getMonth() == 6; -}); -``` - ## `Hurdat.filter(query)` A method to quickly query for storms @@ -59,7 +29,8 @@ A method to quickly query for storms #### Parameters -`query` - An object containing different conditions to query for +`query` - An function with one parameter to filter items or an object containing different conditions to query for +#### Query object fields **Note**: All `query` parameters are optional - `season` (Number) - Look for storms in a certain year - `namematch` (Regular expression) - Look for storms with names matching a certain regular expression @@ -103,3 +74,11 @@ Find storms that have a track distance of at least 2,500 miles and less than or ```javascript hurdat.filter({"distancemi": [2500, 10000], "date": [new Date(2000, 0, 1), new Date(2500, 0, 1)]}) ``` + +Example usage of using a function to filter storms with the name Henri + +```javascript +hurdat.filter(function(storm) { + return storm.name == "Henri" +}) +``` From 8cbb08bccf789af68bbeeeb267db6e95d2a5ed3a Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:36:53 -0500 Subject: [PATCH 16/19] Fix major issue with storm header finder --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index ab6ddca..19e3d71 100644 --- a/src/index.js +++ b/src/index.js @@ -43,7 +43,7 @@ class Hurdat { var stormdata = [] var stormheader = "" for (var item of raw) { - if (item.split(",").length < 4) { + if (item.split(",").length < 8) { if (stormheader != "") { self.storms.push(new Storm(stormheader, stormdata)) stormdata = [] @@ -209,8 +209,8 @@ class Hurdat { return matches }) - } else if (func instanceof Function) { - return this.storms.filter((storm) => func(storm)) + } else if (query instanceof Function) { + return this.storms.filter((storm) => query(storm)) } else { throw new Error("Filter must be a function or object with query fields") } From ffbd191a421be4bf1b64d5b62d9cb9d8dcf90517 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Sun, 12 Feb 2023 20:37:44 -0500 Subject: [PATCH 17/19] Fix minor typo --- docs/hurdat.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/hurdat.md b/docs/hurdat.md index 4e3b16d..9babd92 100644 --- a/docs/hurdat.md +++ b/docs/hurdat.md @@ -79,6 +79,6 @@ Example usage of using a function to filter storms with the name Henri ```javascript hurdat.filter(function(storm) { - return storm.name == "Henri" + return storm.name == "HENRI"; }) ``` From e79e23f93ae3cf55f8b6e004e15bbaf7e50f6767 Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Fri, 17 Feb 2023 21:39:40 -0500 Subject: [PATCH 18/19] Update README.md --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 2943963..d377490 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,11 @@ An extremely simple and ultra lightweight package for parsing through Hurdat2 da # Usage ## Installation This package can be installed using a simple `npm install` command -``` +```bash npm install hurdatparser ``` -You can import it into your project using `import` -``` +You can import it using `import` +```javascript import { Hurdat, Util, Point } from "hurdatparser" ``` ## [Documentation](https://github.com/wilburcoding/hurdatparser/tree/main/docs) From 3df95106ee54074f773e6909a754c6192065ddbb Mon Sep 17 00:00:00 2001 From: Wilbur Wei <66228004+wilburcoding@users.noreply.github.com> Date: Fri, 17 Feb 2023 21:40:24 -0500 Subject: [PATCH 19/19] Update TODO.md --- TODO.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TODO.md b/TODO.md index 6672c4a..3cf55bf 100644 --- a/TODO.md +++ b/TODO.md @@ -1,2 +1,5 @@ -- [ ] Add support for multiple basins +- [x] Add support for multiple basins +- [ ] Add JTWC data support +- [ ] PAGASA data support +- [ ] Add SPC storm report data? - [ ] Proofread docs and create examples