@atmosx/event-product-parser 3.0.6 → 3.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/.github/docs/docs-functions.md +2 -2
  2. package/.github/docs/docs-general-configurations.md +2 -12
  3. package/.github/docs/docs-integrations.md +4 -3
  4. package/.github/docs/docs-listeners.md +1 -1
  5. package/.github/docs/docs-source-configuration.md +1 -1
  6. package/.github/docs/docs-technical.md +1 -1
  7. package/{.github/README.md → README.md} +15 -9
  8. package/dist/cjs/index.cjs +24073 -7018
  9. package/dist/esm/index.mjs +24035 -6983
  10. package/package.json +56 -47
  11. package/pnpm-workspace.yaml +4 -0
  12. package/src/bootstrap.ts +64 -48
  13. package/src/{@building → building}/CreateEvent.ts +22 -24
  14. package/src/{@building → building}/GetCleanedEvent.ts +2 -2
  15. package/src/{@building → building}/GetEventAttachments.ts +14 -12
  16. package/src/building/GetEventDirection.ts +28 -0
  17. package/src/{@building → building}/GetEventEnhancedName.ts +5 -8
  18. package/src/{@building → building}/GetEventGeometry.ts +19 -13
  19. package/src/{@building → building}/GetEventHeader.ts +13 -13
  20. package/src/{@building → building}/GetEventNodes.ts +21 -19
  21. package/src/{@building → building}/GetEventOffice.ts +13 -13
  22. package/src/building/GetEventProperties.ts +105 -0
  23. package/src/{@building → building}/GetEventSignature.ts +9 -9
  24. package/src/{@building → building}/GetEventTags.ts +3 -3
  25. package/src/building/GetEventTheme.ts +26 -0
  26. package/src/building/GetEventTracking.ts +64 -0
  27. package/src/components/audio/GenerateAudioMessage.ts +149 -0
  28. package/src/{@modules/@eas → components/audio/components}/GetCleanDescription.ts +2 -2
  29. package/src/{@modules/@eas → components/audio/components}/GetFloatPCM16.ts +2 -2
  30. package/src/{@modules/@eas → components/audio/components}/GetMergedPCM16.ts +2 -2
  31. package/src/{@modules/@eas → components/audio/components}/GetPCM16.ts +13 -8
  32. package/src/{@modules/@eas → components/audio/components}/GetPCMToFloat.ts +2 -2
  33. package/src/{@modules/@eas → components/audio/components}/GetSampledPCM16.ts +14 -8
  34. package/src/{@modules/@eas → components/audio/components}/GetTTS.ts +17 -10
  35. package/src/{@modules/@eas → components/audio/components}/GetWavPCM16.ts +7 -7
  36. package/src/{@modules/@eas → components/audio/components}/SetAFSK.ts +13 -8
  37. package/src/{@modules/@eas → components/audio/components}/SetAsciiToBits.ts +2 -2
  38. package/src/{@modules/@eas → components/audio/components}/SetAttentionTone.ts +11 -6
  39. package/src/{@modules/@eas → components/audio/components}/SetNoise.ts +12 -7
  40. package/src/{@modules/@eas → components/audio/components}/SetRadioEffect.ts +12 -7
  41. package/src/{@modules/@eas → components/audio/components}/SetSameHeader.ts +22 -14
  42. package/src/{@modules/@utilities/SetWarning.ts → components/database/CreateQuery.ts} +18 -13
  43. package/src/{@modules/@database → components/database}/GetCachedEvents.ts +18 -15
  44. package/src/components/database/ImportBoundaries.ts +168 -0
  45. package/src/{@modules/@database → components/database}/ImportBroadcastify.ts +14 -24
  46. package/src/components/database/ImportCities.ts +87 -0
  47. package/src/{@modules/@database → components/database}/ImportShapefiles.ts +23 -26
  48. package/src/{@modules/@database → components/database}/ImportStanza.ts +15 -19
  49. package/src/components/database/InitializeDatabase.ts +71 -0
  50. package/src/components/images/GenerateGraphic.ts +234 -0
  51. package/src/components/images/components/CreateRectangle.ts +22 -0
  52. package/src/components/images/components/CreateText.ts +22 -0
  53. package/src/components/images/modules/CreateSVG.ts +37 -0
  54. package/src/components/images/modules/GetGeographicalBoundaries.ts +72 -0
  55. package/src/components/images/modules/GetGeographicalCities.ts +58 -0
  56. package/src/components/images/modules/GetGeographicalEvents.ts +48 -0
  57. package/src/components/images/modules/GetGeometryBounds.ts +82 -0
  58. package/src/components/images/modules/GetParsedBoundary.ts +58 -0
  59. package/src/components/images/modules/GetSVGPath.ts +53 -0
  60. package/src/components/images/modules/NormalizePolygon.ts +57 -0
  61. package/src/{@modules/@stanza → components/stanza}/GetAwipsType.ts +16 -17
  62. package/src/{@modules/@stanza → components/stanza}/ValidateStanza.ts +27 -15
  63. package/src/{@modules/@utilities → components/utilities}/CreateHttp.ts +26 -26
  64. package/src/{@modules/@utilities → components/utilities}/GetFormattedTime.ts +2 -2
  65. package/src/{@modules/@utilities → components/utilities}/GetLatestIssuance.ts +2 -2
  66. package/src/{@modules/@utilities → components/utilities}/GetMatched.ts +10 -5
  67. package/src/{@modules/@utilities → components/utilities}/GetShapeNearestPoint.ts +24 -19
  68. package/src/components/utilities/GetUnionPolygon.ts +36 -0
  69. package/src/components/utilities/QueueManager.ts +70 -0
  70. package/src/{@modules/@utilities → components/utilities}/SetCronSchedule.ts +29 -25
  71. package/src/{@modules/@utilities → components/utilities}/SetDebug.ts +12 -12
  72. package/src/components/utilities/SetEventEmit.ts +42 -0
  73. package/src/{@modules/@utilities → components/utilities}/SetSettings.ts +7 -7
  74. package/src/{@modules/@utilities → components/utilities}/SetSleep.ts +5 -5
  75. package/src/components/utilities/SetTimeoutAction.ts +64 -0
  76. package/src/components/utilities/SetWarning.ts +47 -0
  77. package/src/{@modules/@xmpp → components/xmpp}/DeployXMPP.ts +20 -20
  78. package/src/{@core/CreateListener.ts → components/xmpp/ErrorXMPP.ts} +8 -5
  79. package/src/{@modules/@xmpp → components/xmpp}/OfflineXMPP.ts +13 -13
  80. package/src/{@modules/@xmpp → components/xmpp}/OnlineXMPP.ts +18 -18
  81. package/src/components/xmpp/ReconnectXMPP.ts +64 -0
  82. package/src/{@modules/@xmpp → components/xmpp}/StanzaXMPP.ts +25 -25
  83. package/src/{@core → core}/ClearEvents.ts +9 -9
  84. package/src/{@core → core}/GetEvents.ts +4 -4
  85. package/src/{@core → core}/GetNodes.ts +4 -4
  86. package/src/{@core → core}/GetRandomEvent.ts +4 -4
  87. package/src/{@core → core}/GetVersion.ts +4 -4
  88. package/src/{@core → core}/ManualEvent.ts +23 -24
  89. package/src/{@core → core}/QueryStanza.ts +12 -11
  90. package/src/core/SetNode.ts +87 -0
  91. package/src/{@core → core}/StartService.ts +21 -20
  92. package/src/{@core → core}/StopService.ts +10 -10
  93. package/src/{@enums → enums}/AWIPS.ts +2 -2
  94. package/src/{@enums → enums}/Actions.ts +2 -2
  95. package/src/{@enums → enums}/Cancellation.ts +2 -2
  96. package/src/{@enums → enums}/Causes.ts +2 -2
  97. package/src/{@enums → enums}/Correlations.ts +2 -2
  98. package/src/{@enums → enums}/Enhanced.ts +2 -2
  99. package/src/{@enums → enums}/Events.ts +2 -2
  100. package/src/{@enums → enums}/Expressions.ts +3 -3
  101. package/src/{@enums → enums}/GlobalFilter.ts +2 -2
  102. package/src/{@enums → enums}/Hail.ts +2 -2
  103. package/src/{@enums → enums}/ICAO.ts +2 -2
  104. package/src/{@enums → enums}/Matches.ts +8 -3
  105. package/src/{@enums → enums}/Products.ts +2 -2
  106. package/src/{@enums → enums}/Records.ts +2 -2
  107. package/src/{@enums → enums}/Severity.ts +2 -2
  108. package/src/{@enums → enums}/Shapefiles.ts +2 -2
  109. package/src/{@enums → enums}/States.ts +68 -4
  110. package/src/{@enums → enums}/Status.ts +2 -2
  111. package/src/{@enums → enums}/Strings.ts +2 -2
  112. package/src/{@enums → enums}/Tags.ts +9 -4
  113. package/src/{@enums → enums}/Testing.ts +2 -2
  114. package/src/enums/Themes.ts +70 -0
  115. package/src/events/ParseAPI.ts +129 -0
  116. package/src/{@events → events}/ParseText.ts +24 -22
  117. package/src/{@events → events}/ParseUGC.ts +27 -26
  118. package/src/{@events → events}/ParseVTEC.ts +38 -37
  119. package/src/index.ts +57 -37
  120. package/src/manager/MakeEvents.ts +110 -0
  121. package/src/manager/RemoveEvent.ts +74 -0
  122. package/src/{@manager → manager}/SetHash.ts +18 -13
  123. package/src/{@manager → manager}/UpdateEvents.ts +12 -12
  124. package/src/{@manager → manager}/UpdateNode.ts +14 -14
  125. package/src/{@building → manager}/ValidateEvents.ts +47 -57
  126. package/src/{@parsers/@hvtec → parsers/hvtec}/HVExtract.ts +11 -11
  127. package/src/{@parsers/@text → parsers/text}/GetDescriptionFromProduct.ts +20 -21
  128. package/src/{@parsers/@text → parsers/text}/GetEmbededText.ts +7 -6
  129. package/src/parsers/text/GetPolygonFromProduct.ts +71 -0
  130. package/src/{@parsers/@text → parsers/text}/GetStringText.ts +9 -9
  131. package/src/{@parsers/@text → parsers/text}/GetTextFromProduct.ts +12 -12
  132. package/src/parsers/ugc/GetCache.ts +24 -0
  133. package/src/{@parsers/@ugc → parsers/ugc}/GetExpiry.ts +2 -2
  134. package/src/{@parsers/@ugc/GetUGCHeader.ts → parsers/ugc/GetHeader.ts} +4 -4
  135. package/src/{@parsers/@ugc → parsers/ugc}/GetLocations.ts +10 -10
  136. package/src/parsers/ugc/GetZonePolygon.ts +73 -0
  137. package/src/{@parsers/@ugc → parsers/ugc}/GetZones.ts +3 -3
  138. package/src/{@parsers/@ugc → parsers/ugc}/SetCache.ts +13 -8
  139. package/src/{@parsers/@ugc → parsers/ugc}/UGCExtract.ts +14 -14
  140. package/src/{@parsers/@pvtec → parsers/vtec}/GetExpiry.ts +2 -2
  141. package/src/parsers/vtec/VTECExtract.ts +49 -0
  142. package/src/{@types → static}/Attributes.ts +2 -3
  143. package/src/{@types → static}/Event.ts +8 -7
  144. package/src/{@types → static}/Properties.ts +7 -3
  145. package/src/{@types → static}/Stanza.ts +2 -2
  146. package/src/tasks/CreateTasks.ts +123 -0
  147. package/src/tasks/TaskGenerateJSON.ts +34 -0
  148. package/src/tasks/TaskGenerateText.ts +34 -0
  149. package/src/tasks/TaskSendNTFY.ts +97 -0
  150. package/src/tasks/TaskSendWebhook.ts +107 -0
  151. package/src/{@types → types}/Actions.ts +3 -3
  152. package/src/{@types → types}/HVTEC.ts +6 -6
  153. package/src/{@types → types}/Hash.ts +5 -5
  154. package/src/types/Nodes.ts +29 -0
  155. package/src/{@types → types}/Settings.ts +16 -8
  156. package/src/{@types → types}/StanzaCompiled.ts +15 -15
  157. package/src/{@types → types}/UGC.ts +5 -5
  158. package/src/{@modules/@utilities/GetSettings.ts → types/VTEC.ts} +12 -7
  159. package/tools/build.js +47 -0
  160. package/tsconfig.json +28 -1
  161. package/src/@building/GetEventProperties.ts +0 -96
  162. package/src/@building/GetEventTracking.ts +0 -68
  163. package/src/@core/SetNode.ts +0 -81
  164. package/src/@events/ParseAPI.ts +0 -117
  165. package/src/@manager/CreateActions.ts +0 -213
  166. package/src/@manager/MakeEvent.ts +0 -99
  167. package/src/@manager/RemoveEvent.ts +0 -70
  168. package/src/@modules/@database/InitializeDatabase.ts +0 -59
  169. package/src/@modules/@eas/GenerateEASMessage.ts +0 -144
  170. package/src/@modules/@utilities/SetEventEmit.ts +0 -41
  171. package/src/@modules/@utilities/SetListener.ts +0 -30
  172. package/src/@modules/@utilities/SetTimeoutAction.ts +0 -64
  173. package/src/@modules/@xmpp/ErrorXMPP.ts +0 -27
  174. package/src/@modules/@xmpp/ReconnectXMPP.ts +0 -64
  175. package/src/@parsers/@pvtec/VTECExtract.ts +0 -49
  176. package/src/@parsers/@text/GetPolygonFromProduct.ts +0 -53
  177. package/src/@parsers/@text/GetXML.ts +0 -61
  178. package/src/@parsers/@ugc/GetCache.ts +0 -24
  179. package/src/@parsers/@ugc/GetZonePolygon.ts +0 -111
  180. package/src/@types/VTEC.ts +0 -30
  181. package/tsup.config.ts +0 -16
@@ -0,0 +1,72 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { EnumStateFIPS } from "@Enums/States"
21
+ import { CreateQuery } from "@Database/CreateQuery"
22
+
23
+ interface GetGeographicalBoundariesOptions {
24
+ Regions: string[] | null
25
+ }
26
+
27
+ interface GeographicalBoundariesResponse {
28
+ states: any[]
29
+ counties: any[]
30
+ }
31
+
32
+ export const GetGeographicalBoundaries = ({ Regions }: GetGeographicalBoundariesOptions): GeographicalBoundariesResponse => {
33
+ const states = []
34
+ const counties = []
35
+ if (!Regions) {
36
+ const stateBoundaries = CreateQuery({
37
+ Query: `SELECT * FROM boundaries WHERE type = 'state' AND state NOT IN ('AK', 'HI')`,
38
+ })
39
+ const countyBoundaries = CreateQuery({
40
+ Query: `SELECT * FROM boundaries WHERE type = 'county' AND state NOT IN ('AK', 'HI')`,
41
+ })
42
+ states.push(...stateBoundaries)
43
+ counties.push(...countyBoundaries)
44
+ return { states, counties }
45
+ }
46
+ for (const region of Regions) {
47
+ const match = region.match(/^([A-Z]{2})[CZ](\d{3})$/i) ?? null
48
+ if (!match) {
49
+ const children = CreateQuery({
50
+ Query: `SELECT * FROM boundaries WHERE type = 'county' AND state = ?`,
51
+ Parameters: [region]
52
+ })
53
+ const parent = CreateQuery({
54
+ Query: `SELECT * FROM boundaries WHERE type = 'state' AND state = ?`,
55
+ Parameters: [region]
56
+ })
57
+ for (const child of children) {
58
+ counties.push(child)
59
+ }
60
+ states.push(...parent)
61
+ } else {
62
+ const [, state, county] = match
63
+ const fips = Object.entries(EnumStateFIPS).find(([, value]) => value === state)?.[0]
64
+ const child = CreateQuery({
65
+ Query: `SELECT * FROM boundaries WHERE type = 'county' AND id = ?`,
66
+ Parameters: [fips + county]
67
+ })
68
+ counties.push(...child);
69
+ }
70
+ }
71
+ return { states, counties }
72
+ }
@@ -0,0 +1,58 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { CreateQuery } from "@Database/CreateQuery"
21
+
22
+ interface GetGeographicalCitiesOptions {
23
+ Regions: string[] | null
24
+ }
25
+
26
+ interface GeographicalCitiesResponse {
27
+ cities: {
28
+ id: string;
29
+ name: string;
30
+ state: string;
31
+ county: string;
32
+ population: number;
33
+ lat: number;
34
+ lon: number
35
+ }[]
36
+ }
37
+
38
+ export const GetGeographicalCities = ({ Regions }: GetGeographicalCitiesOptions): GeographicalCitiesResponse => {
39
+ const cities = []
40
+ if (!Regions) {
41
+ const cityBoundaries = CreateQuery({
42
+ Query: `SELECT * FROM cities WHERE state NOT IN ('AK', 'HI')`,
43
+ })
44
+ cities.push(...cityBoundaries)
45
+ return { cities }
46
+ }
47
+ for (const region of Regions) {
48
+ const match = region.match(/^([A-Z]{2})[CZ](\d{3})$/i) ?? null
49
+ if (!match) {
50
+ const parent = CreateQuery({
51
+ Query: `SELECT * FROM cities WHERE state = ?`,
52
+ Parameters: [region]
53
+ })
54
+ cities.push(...parent)
55
+ }
56
+ }
57
+ return { cities }
58
+ }
@@ -0,0 +1,48 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { TypeEvent } from "StaticTypes/Event"
21
+ import { Bootstrap } from "@Bootstrap"
22
+
23
+ interface GetGeographicalEventsOptions {
24
+ Regions: string[] | null
25
+ Event?: TypeEvent
26
+ }
27
+
28
+ export const GetGeographicalEvents = ({ Regions, Event }: GetGeographicalEventsOptions): TypeEvent[] => {
29
+ const events = Bootstrap.Cache.Events.features
30
+ if (Event) { return [Event] }
31
+ if (!Regions) { return events }
32
+ return events.filter(event => {
33
+ const ugcs = event.properties?.geocode?.ugc ?? []
34
+ return Regions.some(region => {
35
+ const normalized = region.trim().toUpperCase()
36
+ const ugcMatch = normalized.match(/^([A-Z]{2})[CZ](\d{3})$/)
37
+ if (ugcMatch) {
38
+ return ugcs.some(ugc => ugc.trim().toUpperCase() === normalized)
39
+ }
40
+ const stateMatch = normalized.match(/^[A-Z]{2}$/)
41
+ if (stateMatch) {
42
+ return ugcs.some(ugc => ugc.trim().toUpperCase().startsWith(`${normalized}Z`) || ugc.trim().toUpperCase().startsWith(`${normalized}C`))
43
+ }
44
+ return false
45
+ })
46
+ })
47
+
48
+ }
@@ -0,0 +1,82 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ interface GetGeometryBoundsOptions {
21
+ Geometry: GeoJSON.Geometry
22
+ Padding: number
23
+ }
24
+
25
+ interface GeometryBounds {
26
+ Bounds: {
27
+ minLon: number
28
+ minLat: number
29
+ maxLon: number
30
+ maxLat: number
31
+ }
32
+ Search: {
33
+ minLon: number
34
+ minLat: number
35
+ maxLon: number
36
+ maxLat: number
37
+ }
38
+ }
39
+
40
+ export const GetGeometryBounds = ({ Geometry, Padding }: GetGeometryBoundsOptions): GeometryBounds => {
41
+ let minLon = Infinity;
42
+ let minLat = Infinity;
43
+ let maxLon = -Infinity;
44
+ let maxLat = -Infinity;
45
+ const ProcessCoordinate = (coordinate: GeoJSON.Position): void => {
46
+ const [lon, lat] = coordinate;
47
+ if (!Number.isFinite(lon) || !Number.isFinite(lat)) {
48
+ return;
49
+ }
50
+ minLon = Math.min(minLon, lon);
51
+ minLat = Math.min(minLat, lat);
52
+ maxLon = Math.max(maxLon, lon);
53
+ maxLat = Math.max(maxLat, lat);
54
+ };
55
+ const ProcessRing = (ring: GeoJSON.Position[]): void => {
56
+ for (const coordinate of ring) {
57
+ ProcessCoordinate(coordinate);
58
+ }
59
+ };
60
+ if (Geometry.type === `Polygon`) {
61
+ for (const ring of Geometry.coordinates) {
62
+ ProcessRing(ring);
63
+ }
64
+ } else if (Geometry.type === `MultiPolygon`) {
65
+ for (const polygon of Geometry.coordinates) {
66
+ for (const ring of polygon) {
67
+ ProcessRing(ring);
68
+ }
69
+ }
70
+ }
71
+ const centerLat = (minLat + maxLat) / 2;
72
+ const latPadding = Padding / 69;
73
+ const lonPadding = Padding / (69 * Math.cos(centerLat * Math.PI / 180));
74
+ const searchMinLon = minLon - lonPadding;
75
+ const searchMaxLon = maxLon + lonPadding;
76
+ const searchMinLat = minLat - latPadding;
77
+ const searchMaxLat = maxLat + latPadding;
78
+ return {
79
+ Search: { minLon: searchMinLon, minLat: searchMinLat, maxLon: searchMaxLon, maxLat: searchMaxLat },
80
+ Bounds: { minLon, minLat, maxLon, maxLat }
81
+ };
82
+ };
@@ -0,0 +1,58 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ interface BoundaryRow {
21
+ id: string
22
+ type: `state` | `county`
23
+ state: string
24
+ name: string
25
+ geometry: string
26
+ }
27
+
28
+ type BoundaryProperties = {
29
+ state: string
30
+ name: string
31
+ id?: string
32
+ }
33
+
34
+ type BoundaryFeature = GeoJSON.Feature<GeoJSON.Polygon | GeoJSON.MultiPolygon, BoundaryProperties>
35
+
36
+ export const GetParsedBoundary = (rows: BoundaryRow[]): BoundaryFeature[] => {
37
+ const features: BoundaryFeature[] = []
38
+ for (const row of rows) {
39
+ try {
40
+ const geometry = JSON.parse(row.geometry) as GeoJSON.Geometry
41
+ if ( !geometry || typeof geometry !== `object` || (geometry.type !== `Polygon` && geometry.type !== `MultiPolygon`) ) {
42
+ continue
43
+ }
44
+ features.push({
45
+ type: `Feature`,
46
+ properties: {
47
+ state: row.state,
48
+ name: row.name,
49
+ ...(row.type === `county` ? { id: row.id } : {})
50
+ },
51
+ geometry
52
+ })
53
+ } catch {
54
+ continue
55
+ }
56
+ }
57
+ return features
58
+ }
@@ -0,0 +1,53 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { NormalizePolygon } from "@Image/modules/NormalizePolygon"
21
+
22
+ interface GenerateEventPolygonsOptions {
23
+ Polygons: GeoJSON.Polygon | GeoJSON.MultiPolygon | null
24
+ IPath: (feature: GeoJSON.Feature) => string | null
25
+ Map: boolean
26
+ Settings: {
27
+ BorderColor: string
28
+ BorderWidth: number
29
+ FillColor: string
30
+ FillOpacity: number
31
+ }
32
+ }
33
+
34
+ export const GetSVGPath = ({ Polygons, IPath, Settings, Map }: GenerateEventPolygonsOptions): string => {
35
+ if (!Polygons) return
36
+ const feature: GeoJSON.Feature = {
37
+ type: `Feature`,
38
+ properties: {},
39
+ geometry: !Map ? NormalizePolygon(Polygons) : Polygons,
40
+ };
41
+ const d = IPath(feature);
42
+ if (!d) return ``;
43
+ return `<path
44
+ d="${d}"
45
+ fill="${Settings.FillColor}"
46
+ fill-opacity="${Settings.FillOpacity}"
47
+ fill-rule="evenodd"
48
+ stroke="${Settings.BorderColor}"
49
+ stroke-width="${Settings.BorderWidth}"
50
+ stroke-linejoin="round"
51
+ stroke-linecap="round"
52
+ />`;
53
+ };
@@ -0,0 +1,57 @@
1
+ /*
2
+ _ _ _ __ __
3
+ /\ | | | | (_) \ \ / /
4
+ / \ | |_ _ __ ___ ___ ___ _ __ | |__ ___ _ __ _ ___ \ V /
5
+ / /\ \| __| '_ ` _ \ / _ \/ __| '_ \| '_ \ / _ \ '__| |/ __| > <
6
+ / ____ \ |_| | | | | | (_) \__ \ |_) | | | | __/ | | | (__ / . \
7
+ /_/ \_\__|_| |_| |_|\___/|___/ .__/|_| |_|\___|_| |_|\___/_/ \_\
8
+ | |
9
+ |_|
10
+
11
+ Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
+ Discord: https://atmosphericx-discord.scriptkitty.cafe
13
+ Ko-Fi: https://ko-fi.com/k3yomi
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
+
16
+ Independent Package: @atmosx/event-product-parser
17
+
18
+ */
19
+
20
+ import { geoArea } from "d3-geo";
21
+
22
+ export const NormalizeD3Polygon = (geometry: GeoJSON.Polygon | GeoJSON.MultiPolygon): GeoJSON.Polygon | GeoJSON.MultiPolygon => {
23
+ const area = geoArea(geometry);
24
+ if (area > 2 * Math.PI) {
25
+ if (geometry.type === `Polygon`) {
26
+ return {
27
+ type: `Polygon`,
28
+ coordinates: geometry.coordinates.map(ring => ring.slice().reverse())
29
+ };
30
+ }
31
+ return {
32
+ type: `MultiPolygon`,
33
+ coordinates: geometry.coordinates.map(polygon => polygon.map(ring => ring.slice().reverse()))
34
+ };
35
+ }
36
+ return geometry;
37
+ };
38
+
39
+ export const NormalizePolygon = (geometry: GeoJSON.Geometry): GeoJSON.Geometry => {
40
+ if (geometry.type !== `Polygon` && geometry.type !== `MultiPolygon`) {
41
+ return geometry;
42
+ }
43
+ const reverseRing = (ring: number[][]) => {
44
+ const reversed = ring.slice().reverse();
45
+ return reversed;
46
+ };
47
+ if (geometry.type === `Polygon`) {
48
+ return {
49
+ type: `Polygon`,
50
+ coordinates: geometry.coordinates.map((ring, index) => index === 0 ? reverseRing(ring) : ring.slice().reverse())
51
+ };
52
+ }
53
+ return {
54
+ type: `MultiPolygon`,
55
+ coordinates: geometry.coordinates.map(polygon => polygon.map((ring, index) => index === 0 ? reverseRing(ring) : ring.slice().reverse()))
56
+ };
57
+ }
@@ -11,38 +11,37 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- import { TypeAttributes } from "../../@types/Attributes"
21
- import { EnumAWIPS } from "../../@enums/AWIPS"
20
+ import { TypeAttributes } from "StaticTypes/Attributes"
21
+ import { EnumAWIPS } from "@Enums/AWIPS"
22
22
 
23
23
  interface GetAwipsTypeOptions {
24
- attributes: TypeAttributes
24
+ Attributes: TypeAttributes
25
25
  }
26
26
 
27
27
  interface GetAwipsTypeResponse {
28
- type: string
29
- prefix: string
30
- discovered: boolean
28
+ Type: string
29
+ Prefix: string
30
+ Discovered: boolean
31
31
  }
32
32
 
33
- export const GetAwipsType = (options: GetAwipsTypeOptions): GetAwipsTypeResponse => {
34
- const attributes = options.attributes;
35
- if (!attributes.awipsid) {
33
+ export const GetAwipsType = ({ Attributes }: GetAwipsTypeOptions): GetAwipsTypeResponse => {
34
+ if (!Attributes.awipsid) {
36
35
  return {
37
- type: null,
38
- prefix: null,
39
- discovered: false
36
+ Type: null,
37
+ Prefix: null,
38
+ Discovered: false
40
39
  }
41
40
  }
42
41
  for (const [prefix, type] of Object.entries(EnumAWIPS)) {
43
- if (attributes.awipsid.startsWith(prefix)) {
44
- return { type, prefix, discovered: true }
42
+ if (Attributes.awipsid.startsWith(prefix)) {
43
+ return { Type: type, Prefix: prefix, Discovered: true }
45
44
  }
46
45
  }
47
- return { type: options.attributes.awipsid, prefix: options.attributes.awipsid, discovered: false }
46
+ return { Type: Attributes.awipsid, Prefix: Attributes.awipsid, Discovered: false }
48
47
  }
@@ -11,40 +11,52 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
- import { TypeStanza } from "../../@types/Stanza"
21
- import { TypeStanzaCompiled } from "../../@types/StanzaCompiled"
22
- import { EnumExpressions } from "../../@enums/Expressions"
23
- import { GetAwipsType } from "./GetAwipsType"
20
+ import { TypeStanza } from "StaticTypes/Stanza"
21
+ import { TypeStanzaCompiled } from "Types/StanzaCompiled"
22
+ import { EnumExpressions } from "@Enums/Expressions"
23
+ import { GetAwipsType } from "@Stanza/GetAwipsType"
24
24
 
25
25
  interface ValidateStanzaOptions {
26
- stanza: TypeStanza
26
+ Stanza: TypeStanza
27
27
  }
28
28
 
29
- export const ValidateStanza = (options: ValidateStanzaOptions): TypeStanzaCompiled => {
30
- if (options.stanza.is(`message`)) {
31
- const cb = options.stanza.getChild(`x`) as TypeStanza;
29
+ export const ValidateStanza = ({ Stanza }: ValidateStanzaOptions): TypeStanzaCompiled => {
30
+ if (Stanza.is(`message`)) {
31
+ const cb = Stanza.getChild(`x`) as TypeStanza;
32
32
  if (cb && cb.children) {
33
33
  const message = unescape(cb.children[0]);
34
34
  const attributes = cb.attrs;
35
35
  if (attributes.awipsid && attributes.awipsid.length > 1) {
36
36
  const isCapEvent = message.includes(`<?xml`);
37
37
  const isCapAreaDescription = message.includes(`<areaDesc>`)
38
- const isVTEC = message.match(EnumExpressions.pvtec) != null;
38
+ const isVTEC = message.match(EnumExpressions.vtec) != null;
39
39
  const isUGC = message.match(EnumExpressions.ugc1) != null;
40
- const getType = GetAwipsType({ attributes: attributes})
41
- if (getType.type != null) {
40
+ const getType = GetAwipsType({ Attributes: attributes})
41
+ if (getType.Type != null) {
42
42
  return {
43
- message, attributes, isCapEvent, isVTEC, isUGC, isCapAreaDescription, isIgnored: false, isNWWS: true, getType
43
+ Message: message,
44
+ Attributes: attributes,
45
+ CapEvent: isCapEvent,
46
+ VTEC: isVTEC,
47
+ UGC: isUGC,
48
+ CapAreaDescription: isCapAreaDescription,
49
+ Ignored: false,
50
+ NWWS: true,
51
+ Type: {
52
+ Type: getType.Type,
53
+ Prefix: getType.Prefix,
54
+ Discovered: getType.Discovered
55
+ }
44
56
  }
45
57
  }
46
58
  }
47
59
  }
48
60
  }
49
- return { isIgnored: true}
61
+ return { Ignored: true}
50
62
  }
@@ -11,34 +11,34 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
  */
19
19
 
20
20
  interface CreateHttpOptions {
21
- url: string
22
- headers?: any
23
- timeout?: number
24
- auth?: {
25
- username: string
26
- password: string
21
+ URL: string
22
+ Headers?: any
23
+ Timeout?: number
24
+ Auth?: {
25
+ Username: string
26
+ Password: string
27
27
  }
28
- method?: `GET` | `POST` | `PUT` | `DELETE`
29
- body?: any;
30
- formData?: any;
28
+ Method?: `GET` | `POST` | `PUT` | `DELETE`
29
+ Body?: any;
30
+ Form?: any;
31
31
  }
32
32
 
33
- export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
33
+ export const CreateHttp = async ({ URL, Headers, Timeout, Auth, Method, Body, Form }: CreateHttpOptions): Promise<any> => {
34
34
  const requestOptions: RequestInit = {
35
- method: options.method ?? "GET",
36
- headers: options.headers ?? {
35
+ method: Method ?? "GET",
36
+ headers: Headers ?? {
37
37
  "User-Agent": "AtmosphericX",
38
38
  "Accept": "application/geo+json, text/plain, */*; q=0.9",
39
39
  "Accept-Language": "en-US,en;q=0.9",
40
40
  },
41
- signal: AbortSignal.timeout(options.timeout ?? 10_000),
41
+ signal: AbortSignal.timeout(Timeout ?? 10_000),
42
42
  redirect: "follow"
43
43
  };
44
44
 
@@ -47,8 +47,8 @@ export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
47
47
  return { error: error, options: requestOptions, status, message };
48
48
  }
49
49
 
50
- if (options?.auth) {
51
- const authString = `${options.auth.username}:${options.auth.password}`;
50
+ if (Auth) {
51
+ const authString = `${Auth.Username}:${Auth.Password}`;
52
52
  const encodedAuth = Buffer.from(authString).toString("base64");
53
53
  requestOptions.headers = {
54
54
  ...requestOptions.headers,
@@ -56,20 +56,20 @@ export const CreateHttp = async (options: CreateHttpOptions): Promise<any> => {
56
56
  };
57
57
  }
58
58
 
59
- if (options?.formData) {
60
- requestOptions.body = options.formData;
61
- } else if (options?.body != undefined) {
59
+ if (Form) {
60
+ requestOptions.body = Form;
61
+ } else if (Body != undefined) {
62
62
  requestOptions.body =
63
- options.body instanceof FormData
64
- ? options.body
65
- : typeof options.body === "string"
66
- ? options.body
67
- : JSON.stringify(options.body);
63
+ Body instanceof FormData
64
+ ? Body
65
+ : typeof Body === "string"
66
+ ? Body
67
+ : JSON.stringify(Body);
68
68
  }
69
69
 
70
70
  try {
71
71
  const response = await fetch(
72
- options?.url ?? `https://api.weather.gov/alerts/active`,
72
+ URL ?? `https://api.weather.gov/alerts/active`,
73
73
  requestOptions
74
74
  )
75
75
  const body = await response.text();
@@ -11,9 +11,9 @@
11
11
  Created with ♥ by the AtmosphericX Team (KiyoWx, StarflightWx, & CJ Ziegler)
12
12
  Discord: https://atmosphericx-discord.scriptkitty.cafe
13
13
  Ko-Fi: https://ko-fi.com/k3yomi
14
- Documentation: http://localhost/documentation | https://atmosphericx.scriptkitty.cafe/documentation
14
+ Documentation: https://atmosphericx.scriptkitty.cafe/documentation
15
15
 
16
- Internal Package: @atmosx/event-product-parser
16
+ Independent Package: @atmosx/event-product-parser
17
17
 
18
18
 
19
19
  */