metar-taf-parser 1.3.1 → 3.1.0

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 (121) hide show
  1. package/README.md +125 -13
  2. package/dist/command/common.js +14 -12
  3. package/dist/command/metar/AltimeterCommand.d.ts +7 -0
  4. package/dist/command/metar/AltimeterCommand.js +26 -0
  5. package/dist/command/metar/AltimeterMercuryCommand.d.ts +7 -0
  6. package/dist/command/metar/AltimeterMercuryCommand.js +51 -0
  7. package/dist/command/metar/RunwayCommand.d.ts +7 -0
  8. package/dist/command/metar/RunwayCommand.js +60 -0
  9. package/dist/command/metar/TemperatureCommand.d.ts +7 -0
  10. package/dist/command/metar/TemperatureCommand.js +51 -0
  11. package/dist/command/metar.d.ts +1 -22
  12. package/dist/command/metar.js +11 -115
  13. package/dist/command/remark/CeilingHeightCommand.d.ts +18 -0
  14. package/dist/command/remark/CeilingHeightCommand.js +40 -0
  15. package/dist/command/remark/CeilingSecondLocationCommand.d.ts +12 -0
  16. package/dist/command/remark/CeilingSecondLocationCommand.js +40 -0
  17. package/dist/command/remark/Command.d.ts +8 -0
  18. package/dist/command/remark/Command.js +9 -0
  19. package/dist/command/remark/DefaultCommand.d.ts +11 -0
  20. package/dist/command/remark/DefaultCommand.js +38 -0
  21. package/dist/command/remark/HailSizeCommand.d.ts +11 -0
  22. package/dist/command/remark/HailSizeCommand.js +38 -0
  23. package/dist/command/remark/HourlyMaximumMinimumTemperatureCommand.d.ts +18 -0
  24. package/dist/command/remark/HourlyMaximumMinimumTemperatureCommand.js +39 -0
  25. package/dist/command/remark/HourlyMaximumTemperatureCommand.d.ts +14 -0
  26. package/dist/command/remark/HourlyMaximumTemperatureCommand.js +38 -0
  27. package/dist/command/remark/HourlyMinimumTemperatureCommand.d.ts +14 -0
  28. package/dist/command/remark/HourlyMinimumTemperatureCommand.js +38 -0
  29. package/dist/command/remark/HourlyPrecipitationAmountCommand.d.ts +14 -0
  30. package/dist/command/remark/HourlyPrecipitationAmountCommand.js +38 -0
  31. package/dist/command/remark/HourlyPressureCommand.d.ts +32 -0
  32. package/dist/command/remark/HourlyPressureCommand.js +40 -0
  33. package/dist/command/remark/HourlyTemperatureDewPointCommand.d.ts +18 -0
  34. package/dist/command/remark/HourlyTemperatureDewPointCommand.js +52 -0
  35. package/dist/command/remark/IceAccretionCommand.d.ts +15 -0
  36. package/dist/command/remark/IceAccretionCommand.js +38 -0
  37. package/dist/command/remark/ObscurationCommand.d.ts +14 -0
  38. package/dist/command/remark/ObscurationCommand.js +44 -0
  39. package/dist/command/remark/PrecipitationAmount24HourCommand.d.ts +14 -0
  40. package/dist/command/remark/PrecipitationAmount24HourCommand.js +39 -0
  41. package/dist/command/remark/PrecipitationAmount36HourCommand.d.ts +15 -0
  42. package/dist/command/remark/PrecipitationAmount36HourCommand.js +41 -0
  43. package/dist/command/remark/PrecipitationBegCommand.d.ts +15 -0
  44. package/dist/command/remark/PrecipitationBegCommand.js +45 -0
  45. package/dist/command/remark/PrecipitationBegEndCommand.d.ts +17 -0
  46. package/dist/command/remark/PrecipitationBegEndCommand.js +46 -0
  47. package/dist/command/remark/PrecipitationEndCommand.d.ts +15 -0
  48. package/dist/command/remark/PrecipitationEndCommand.js +45 -0
  49. package/dist/command/remark/PrevailingVisibilityCommand.d.ts +12 -0
  50. package/dist/command/remark/PrevailingVisibilityCommand.js +41 -0
  51. package/dist/command/remark/SeaLevelPressureCommand.d.ts +11 -0
  52. package/dist/command/remark/SeaLevelPressureCommand.js +39 -0
  53. package/dist/command/remark/SecondLocationVisibilityCommand.d.ts +12 -0
  54. package/dist/command/remark/SecondLocationVisibilityCommand.js +41 -0
  55. package/dist/command/remark/SectorVisibilityCommand.d.ts +13 -0
  56. package/dist/command/remark/SectorVisibilityCommand.js +42 -0
  57. package/dist/command/remark/SmallHailSizeCommand.d.ts +11 -0
  58. package/dist/command/remark/SmallHailSizeCommand.js +38 -0
  59. package/dist/command/remark/SnowDepthCommand.d.ts +11 -0
  60. package/dist/command/remark/SnowDepthCommand.js +38 -0
  61. package/dist/command/remark/SnowIncreaseCommand.d.ts +12 -0
  62. package/dist/command/remark/SnowIncreaseCommand.js +40 -0
  63. package/dist/command/remark/SnowPelletsCommand.d.ts +11 -0
  64. package/dist/command/remark/SnowPelletsCommand.js +37 -0
  65. package/dist/command/remark/SunshineDurationCommand.d.ts +11 -0
  66. package/dist/command/remark/SunshineDurationCommand.js +38 -0
  67. package/dist/command/remark/SurfaceVisibilityCommand.d.ts +11 -0
  68. package/dist/command/remark/SurfaceVisibilityCommand.js +39 -0
  69. package/dist/command/remark/ThunderStormLocationCommand.d.ts +12 -0
  70. package/dist/command/remark/ThunderStormLocationCommand.js +40 -0
  71. package/dist/command/remark/ThunderStormLocationMovingCommand.d.ts +19 -0
  72. package/dist/command/remark/ThunderStormLocationMovingCommand.js +42 -0
  73. package/dist/command/remark/TornadicActivityBegCommand.d.ts +16 -0
  74. package/dist/command/remark/TornadicActivityBegCommand.js +44 -0
  75. package/dist/command/remark/TornadicActivityBegEndCommand.d.ts +18 -0
  76. package/dist/command/remark/TornadicActivityBegEndCommand.js +46 -0
  77. package/dist/command/remark/TornadicActivityEndCommand.d.ts +16 -0
  78. package/dist/command/remark/TornadicActivityEndCommand.js +44 -0
  79. package/dist/command/remark/TowerVisibilityCommand.d.ts +11 -0
  80. package/dist/command/remark/TowerVisibilityCommand.js +39 -0
  81. package/dist/command/remark/VariableSkyCommand.d.ts +12 -0
  82. package/dist/command/remark/VariableSkyCommand.js +41 -0
  83. package/dist/command/remark/VariableSkyHeightCommand.d.ts +13 -0
  84. package/dist/command/remark/VariableSkyHeightCommand.js +43 -0
  85. package/dist/command/remark/VirgaDirectionCommand.d.ts +12 -0
  86. package/dist/command/remark/VirgaDirectionCommand.js +40 -0
  87. package/dist/command/remark/WaterEquivalentSnowCommand.d.ts +11 -0
  88. package/dist/command/remark/WaterEquivalentSnowCommand.js +38 -0
  89. package/dist/command/remark/WindPeakCommandCommand.d.ts +17 -0
  90. package/dist/command/remark/WindPeakCommandCommand.js +42 -0
  91. package/dist/command/remark/WindShiftCommand.d.ts +12 -0
  92. package/dist/command/remark/WindShiftCommand.js +38 -0
  93. package/dist/command/remark/WindShiftFropaCommand.d.ts +12 -0
  94. package/dist/command/remark/WindShiftFropaCommand.js +38 -0
  95. package/dist/command/remark.d.ts +100 -194
  96. package/dist/command/remark.js +136 -755
  97. package/dist/commons/converter.d.ts +14 -2
  98. package/dist/commons/converter.js +53 -5
  99. package/dist/commons/errors.d.ts +6 -2
  100. package/dist/commons/errors.js +15 -8
  101. package/dist/commons/i18n.d.ts +2 -2
  102. package/dist/commons/i18n.js +9 -3
  103. package/dist/dates/metar.d.ts +5 -0
  104. package/dist/dates/metar.js +8 -0
  105. package/dist/dates/taf.d.ts +28 -0
  106. package/dist/dates/taf.js +17 -0
  107. package/dist/forecast/forecast.d.ts +36 -0
  108. package/dist/forecast/forecast.js +72 -0
  109. package/dist/helpers/date.d.ts +11 -0
  110. package/dist/helpers/date.js +56 -0
  111. package/dist/helpers/helpers.d.ts +7 -0
  112. package/dist/helpers/helpers.js +14 -1
  113. package/dist/index.d.ts +23 -2
  114. package/dist/index.js +24 -7
  115. package/dist/model/enum.d.ts +44 -0
  116. package/dist/model/enum.js +50 -1
  117. package/dist/model/model.d.ts +84 -19
  118. package/dist/model/model.js +3 -1
  119. package/dist/parser/parser.d.ts +13 -6
  120. package/dist/parser/parser.js +64 -30
  121. package/package.json +3 -3
package/README.md CHANGED
@@ -1,9 +1,21 @@
1
1
  # ✈️ [metar-taf-parser](https://aeharding.github.io/metar-taf-parser)
2
2
 
3
- Parser for METeorological Aerodrome Reports (METARs) and Terminal Aerodrome Forecasts (TAFs). This is a port of [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) to Typescript. It's dependency-free, fully typed, tested, has i18n support, and can run on Node or in the browser.
3
+ Parser for METeorological Aerodrome Reports (METARs) and Terminal Aerodrome Forecasts (TAFs). This is a port of [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) to Typescript with some additional features.
4
4
 
5
5
  [Check out the demo here](https://aeharding.github.io/metar-taf-parser)
6
6
 
7
+ Features:
8
+
9
+ - ✈️ Complete METAR and TAF parsing
10
+ - 🛠 Fully typed
11
+ - 🪶 Dependency free
12
+ - 🧪 Full test suite
13
+ - ✅ Runs anywhere: Web browser or Node
14
+ - 🌎 i18n: Translations
15
+ - 🌏 i18n: Handling international TAF & METAR report format differences
16
+ - 🌪 Remark parsing to human and machine readable formats
17
+ - 🗓 [`Forecast` abstraction](https://aeharding.github.io/metar-taf-parser/forecast) to easily query TAF reports by `Date`
18
+
7
19
  ## Installation
8
20
 
9
21
  ```sh
@@ -14,31 +26,131 @@ npm i --save metar-taf-parser
14
26
 
15
27
  ## Usage
16
28
 
17
- ### Parse a METAR
29
+ ### Parsing
30
+
31
+ The `parseMetar` & `parseTAF` functions are designed to parse the raw report string into an object representation of a METAR/TAF.
32
+
33
+ #### `parseMetar`
18
34
 
19
35
  ```ts
20
- import { parseMetar } from 'metar-taf-parser'
36
+ import { parseMetar } from "metar-taf-parser";
37
+
38
+ const metar = parseMetar(rawMetarString);
21
39
 
22
- const metar = parseMetar(rawMetarString)
40
+ // -or-
41
+
42
+ // Optionally pass a date (approximately when the report was issued, +/- a week)
43
+ // to get the issued date on the report:
44
+ const datedMetar = parseMetar(rawMetarString, { date: new Date() });
23
45
  ```
24
46
 
25
- ### Parse a TAF
47
+ #### `parseTAF`
48
+
49
+ 👉 **Note:** One of the common use cases for TAF reports is to get relevant forecast data for a given date. Check out [the `Forecast` abstraction](#higher-level-parsing-the-forecast-abstraction) below which may provide TAF data in a more normalized format, depending on your use case.
26
50
 
27
51
  ```ts
28
- import { parseTAF } from 'metar-taf-parser'
52
+ import { parseTAF } from "metar-taf-parser";
53
+
54
+ const taf = parseTAF(rawTAFString);
55
+
56
+ // -or-
57
+
58
+ // Optionally pass a date (approximately when the report was issued, +/- a week)
59
+ // to get the report issued and trend validity dates (start/end) on the report:
60
+ const datedTAF = parseTAF(rawTAFString, { date: new Date() });
61
+ ```
62
+
63
+ ### Higher level parsing: The Forecast abstraction
64
+
65
+ TAF reports are a little funky... FM, BECMG, PROB, etc. You may find the `Forecast` abstraction more helpful.
66
+
67
+ #### `parseTAFAsForecast`
68
+
69
+ Returns a more normalized TAF report. Most notably: while the `parseTAF` function returns initial weather conditions on the base of the returned result (and further conditions on `trends[]`), the `parseTAFAsForecast` function returns the initial weather conditions as the first element of the `forecast[]` property, followed by subsequent trends. This makes it much easier to iterate though.
70
+
71
+ ```ts
72
+ import { parseTAFAsForecast } from "metar-taf-parser";
73
+
74
+ // You must provide an issued date to use the Forecast abstraction
75
+ const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
76
+
77
+ console.log(report.forecast);
78
+ ```
79
+
80
+ #### `getCompositeForecastForDate`
81
+
82
+ > ⚠️ **Warning:** Experimental API
83
+
84
+ Provides all relevant weather conditions for a given timestamp. It returns a `ICompositeForecast` with a `base` and `additional` component. The `base` component is the base weather condition period (the FM part of the report) - and there will always be one.
85
+
86
+ The `additional` property is an array of weather condition periods valid for the given timestamp (any `BECMG`, `PROB`, `TEMPO`, etc.)
29
87
 
30
- const taf = parseTAF(rawTAFString)
88
+ You will still need to write some logic to use this API to determine what data to use - for example, if `additional[0].visibility` exists, use it over `base.visibility`.
89
+
90
+ #### Example
91
+
92
+ This example provides an array of hourly weather conditions over the duration of the TAF report.
93
+
94
+ ```ts
95
+ import { eachHourOfInterval } from "date-fns";
96
+ import {
97
+ parseTAFAsForecast,
98
+ getCompositeForecastForDate,
99
+ } from "metar-taf-parser";
100
+
101
+ const report = parseTAFAsForecast(rawTAFString, { date: tafIssuedDate });
102
+
103
+ const forecastPerHour = eachHourOfInterval({
104
+ start: report.start,
105
+ end: report.end,
106
+ }).map((hour) => ({
107
+ hour,
108
+ ...getCompositeForecastForDate(hour, report),
109
+ }));
31
110
  ```
32
111
 
33
112
  ## i18n
34
113
 
114
+ The `description` property in the `Remark` is translated, if available.
115
+
35
116
  ```ts
36
- import { parseMetar } from 'metar-taf-parser'
37
- import de from 'metar-taf-parser/dist/locale/de'
117
+ import { parseMetar } from "metar-taf-parser";
118
+ import de from "metar-taf-parser/dist/locale/de";
38
119
 
39
- const { metar } = await myService.getAirportData('KMSN')
120
+ const rawMetarReport = "KTTN 051853Z 04011KT RMK SLP176";
40
121
 
41
- const metarResult = parseMetar(metar, { locale: de })
122
+ const metarResult = parseMetar(rawMetarReport, {
123
+ locale: de,
124
+ });
125
+
126
+ console.log(metarReport.remarks[0].description);
127
+ ```
128
+
129
+ ## Handling remarks
130
+
131
+ Remarks may be found on base TAF and METARs, along with TAF trends.
132
+
133
+ Each Remark will have a `description` (if translated), `type` and `raw` properties. There are additional properties for each unique remark, depending on the remark's `type`. We can type guard on `type` to access these unique properties.
134
+
135
+ If the remark is not understood, it will have `type` as `RemarkType.Unknown`, with `raw` containing everything until the next understood remark.
136
+
137
+ ### Example
138
+
139
+ ```ts
140
+ import { Remark, RemarkType } from "metar-taf-parser";
141
+
142
+ /**
143
+ * Find the sea level pressure given remarks, if defined
144
+ */
145
+ function findSeaLevelPressure(remarks: Remark[]): number | undefined {
146
+ for (const remark of remarks) {
147
+ switch (remark.type) {
148
+ case RemarkType.SeaLevelPressure:
149
+ // can now access remark.pressure
150
+ return remark.pressure;
151
+ }
152
+ }
153
+ }
42
154
  ```
43
155
 
44
156
  ## Development
@@ -49,8 +161,8 @@ Please see [the example site README.md](example/README.md).
49
161
 
50
162
  ## Contributing
51
163
 
52
- This project is intended to provide feature parity with [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) and will only accept PRs to maintain feature parity or to fix inconsistencies with that project.
164
+ This project is based on [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser) and the parsing should be as similar to that project as possible. That being said, PRs are welcome.
53
165
 
54
166
  ## Acknowledgment
55
167
 
56
- This software port was made possible due to the fantastic work of [@mivek](https://github.com/mivek) in [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser). If you like this project, please [consider buying @mivek a coffee](https://ko-fi.com/mivek).
168
+ This software port was made possible due to the fantastic work of [@mivek](https://github.com/mivek) in [python-metar-taf-parser](https://github.com/mivek/python-metar-taf-parser). If you like this project, please [consider buying @mivek a coffee](https://ko-fi.com/mivek).
@@ -92,8 +92,10 @@ class MainVisibilityCommand {
92
92
  return false;
93
93
  const distance = converter.convertVisibility(matches[1]);
94
94
  if (!container.visibility)
95
- container.visibility = { distance };
96
- container.visibility.distance = distance;
95
+ container.visibility = distance;
96
+ container.visibility = Object.assign(Object.assign({}, container.visibility), distance);
97
+ if (matches[2] === "NDV")
98
+ container.visibility.ndv = true;
97
99
  return true;
98
100
  }
99
101
  }
@@ -136,7 +138,7 @@ class WindVariationCommand {
136
138
  }
137
139
  execute(container, windString) {
138
140
  if (!container.wind)
139
- throw new errors_1.InvalidWeatherStatementError();
141
+ throw new errors_1.UnexpectedParseError();
140
142
  this.parseWindVariation(container.wind, windString);
141
143
  return true;
142
144
  }
@@ -182,7 +184,7 @@ exports.VerticalVisibilityCommand = VerticalVisibilityCommand;
182
184
  _VerticalVisibilityCommand_regex = new WeakMap();
183
185
  class MinimalVisibilityCommand {
184
186
  constructor() {
185
- _MinimalVisibilityCommand_regex.set(this, /^(\d{4}[a-z])$/);
187
+ _MinimalVisibilityCommand_regex.set(this, /^(\d{4}[a-zA-Z]{1,2})$/);
186
188
  }
187
189
  execute(container, visibilityString) {
188
190
  const matches = visibilityString.match(__classPrivateFieldGet(this, _MinimalVisibilityCommand_regex, "f"));
@@ -190,8 +192,10 @@ class MinimalVisibilityCommand {
190
192
  throw new errors_1.UnexpectedParseError("Vertical visibility should be defined");
191
193
  if (!container.visibility)
192
194
  throw new errors_1.UnexpectedParseError("container.visibility not instantiated");
193
- container.visibility.minDistance = +matches[1].slice(0, 4);
194
- container.visibility.minDirection = matches[1][4];
195
+ container.visibility.min = {
196
+ value: +matches[1].slice(0, 4),
197
+ direction: matches[1].slice(4),
198
+ };
195
199
  return true;
196
200
  }
197
201
  canParse(windString) {
@@ -202,12 +206,11 @@ exports.MinimalVisibilityCommand = MinimalVisibilityCommand;
202
206
  _MinimalVisibilityCommand_regex = new WeakMap();
203
207
  class MainVisibilityNauticalMilesCommand {
204
208
  constructor() {
205
- _MainVisibilityNauticalMilesCommand_regex.set(this, /^(\d)*(\s)?((\d\/\d)?SM)$/);
209
+ _MainVisibilityNauticalMilesCommand_regex.set(this, /^(P|M)?(\d)*(\s)?((\d\/\d)?SM)$/);
206
210
  }
207
211
  execute(container, visibilityString) {
208
- if (!container.visibility)
209
- container.visibility = { distance: visibilityString };
210
- container.visibility.distance = visibilityString;
212
+ const distance = converter.convertNauticalMilesVisibility(visibilityString);
213
+ container.visibility = distance;
211
214
  return true;
212
215
  }
213
216
  canParse(windString) {
@@ -230,8 +233,7 @@ class CommandSupplier {
230
233
  ]);
231
234
  }
232
235
  get(input) {
233
- for (let i = 0; i < __classPrivateFieldGet(this, _CommandSupplier_commands, "f").length; i++) {
234
- const command = __classPrivateFieldGet(this, _CommandSupplier_commands, "f")[i];
236
+ for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands, "f")) {
235
237
  if (command.canParse(input))
236
238
  return command;
237
239
  }
@@ -0,0 +1,7 @@
1
+ import { IMetar } from "../../model/model";
2
+ import { ICommand } from "../metar";
3
+ export declare class AltimeterCommand implements ICommand {
4
+ #private;
5
+ canParse(input: string): boolean;
6
+ execute(metar: IMetar, input: string): void;
7
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _AltimeterCommand_regex;
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.AltimeterCommand = void 0;
10
+ const errors_1 = require("../../commons/errors");
11
+ class AltimeterCommand {
12
+ constructor() {
13
+ _AltimeterCommand_regex.set(this, /^Q(\d{4})$/);
14
+ }
15
+ canParse(input) {
16
+ return __classPrivateFieldGet(this, _AltimeterCommand_regex, "f").test(input);
17
+ }
18
+ execute(metar, input) {
19
+ const matches = input.match(__classPrivateFieldGet(this, _AltimeterCommand_regex, "f"));
20
+ if (!matches)
21
+ throw new errors_1.UnexpectedParseError("Match not found");
22
+ metar.altimeter = Math.trunc(+matches[1]);
23
+ }
24
+ }
25
+ exports.AltimeterCommand = AltimeterCommand;
26
+ _AltimeterCommand_regex = new WeakMap();
@@ -0,0 +1,7 @@
1
+ import { IMetar } from "../../model/model";
2
+ import { ICommand } from "../metar";
3
+ export declare class AltimeterMercuryCommand implements ICommand {
4
+ #private;
5
+ canParse(input: string): boolean;
6
+ execute(metar: IMetar, input: string): void;
7
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
+ };
30
+ var _AltimeterMercuryCommand_regex;
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.AltimeterMercuryCommand = void 0;
33
+ const converter = __importStar(require("../../commons/converter"));
34
+ const errors_1 = require("../../commons/errors");
35
+ class AltimeterMercuryCommand {
36
+ constructor() {
37
+ _AltimeterMercuryCommand_regex.set(this, /^A(\d{4})$/);
38
+ }
39
+ canParse(input) {
40
+ return __classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f").test(input);
41
+ }
42
+ execute(metar, input) {
43
+ const matches = input.match(__classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f"));
44
+ if (!matches)
45
+ throw new errors_1.UnexpectedParseError("Match not found");
46
+ const mercury = +matches[1] / 100;
47
+ metar.altimeter = Math.trunc(converter.convertInchesMercuryToPascal(mercury));
48
+ }
49
+ }
50
+ exports.AltimeterMercuryCommand = AltimeterMercuryCommand;
51
+ _AltimeterMercuryCommand_regex = new WeakMap();
@@ -0,0 +1,7 @@
1
+ import { IMetar } from "../../model/model";
2
+ import { ICommand } from "../metar";
3
+ export declare class RunwayCommand implements ICommand {
4
+ #private;
5
+ canParse(input: string): boolean;
6
+ execute(metar: IMetar, input: string): void;
7
+ }
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
3
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
4
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
5
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
6
+ };
7
+ var _RunwayCommand_genericRegex, _RunwayCommand_runwayMaxRangeRegex, _RunwayCommand_runwayRegex;
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.RunwayCommand = void 0;
10
+ const errors_1 = require("../../commons/errors");
11
+ const helpers_1 = require("../../helpers/helpers");
12
+ const enum_1 = require("../../model/enum");
13
+ class RunwayCommand {
14
+ constructor() {
15
+ _RunwayCommand_genericRegex.set(this, /^(R\d{2}\w?\/)/);
16
+ _RunwayCommand_runwayMaxRangeRegex.set(this, /^R(\d{2}\w?)\/(\d{4})V(\d{3,4})([UDN])?(FT)?/);
17
+ _RunwayCommand_runwayRegex.set(this, /^R(\d{2}\w?)\/([MP])?(\d{4})([UDN])?(FT)?$/);
18
+ }
19
+ canParse(input) {
20
+ return __classPrivateFieldGet(this, _RunwayCommand_genericRegex, "f").test(input);
21
+ }
22
+ execute(metar, input) {
23
+ // TODO idk if this matches super well...
24
+ if (__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f").test(input)) {
25
+ const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f"));
26
+ if (!matches)
27
+ throw new errors_1.UnexpectedParseError("Should be able to parse");
28
+ const indicator = matches[2] ? (0, helpers_1.as)(matches[2], enum_1.ValueIndicator) : undefined;
29
+ const trend = matches[4] ? (0, helpers_1.as)(matches[4], enum_1.RunwayInfoTrend) : undefined;
30
+ const unit = matches[5]
31
+ ? (0, helpers_1.as)(matches[5], enum_1.RunwayInfoUnit)
32
+ : enum_1.RunwayInfoUnit.Meters;
33
+ metar.runwaysInfo.push({
34
+ name: matches[1],
35
+ indicator,
36
+ minRange: +matches[3],
37
+ trend,
38
+ unit,
39
+ });
40
+ }
41
+ else if (__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f").test(input)) {
42
+ const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f"));
43
+ if (!matches)
44
+ throw new errors_1.UnexpectedParseError("Should be able to parse");
45
+ const trend = matches[4] ? (0, helpers_1.as)(matches[4], enum_1.RunwayInfoTrend) : undefined;
46
+ const unit = matches[5]
47
+ ? (0, helpers_1.as)(matches[5], enum_1.RunwayInfoUnit)
48
+ : enum_1.RunwayInfoUnit.Meters;
49
+ metar.runwaysInfo.push({
50
+ name: matches[1],
51
+ minRange: +matches[2],
52
+ maxRange: +matches[3],
53
+ trend,
54
+ unit,
55
+ });
56
+ }
57
+ }
58
+ }
59
+ exports.RunwayCommand = RunwayCommand;
60
+ _RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap();
@@ -0,0 +1,7 @@
1
+ import { IMetar } from "../../model/model";
2
+ import { ICommand } from "../metar";
3
+ export declare class TemperatureCommand implements ICommand {
4
+ #private;
5
+ canParse(input: string): boolean;
6
+ execute(metar: IMetar, input: string): void;
7
+ }
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
+ };
30
+ var _TemperatureCommand_regex;
31
+ Object.defineProperty(exports, "__esModule", { value: true });
32
+ exports.TemperatureCommand = void 0;
33
+ const converter = __importStar(require("../../commons/converter"));
34
+ const errors_1 = require("../../commons/errors");
35
+ class TemperatureCommand {
36
+ constructor() {
37
+ _TemperatureCommand_regex.set(this, /^(M?\d{2})\/(M?\d{2})$/);
38
+ }
39
+ canParse(input) {
40
+ return __classPrivateFieldGet(this, _TemperatureCommand_regex, "f").test(input);
41
+ }
42
+ execute(metar, input) {
43
+ const matches = input.match(__classPrivateFieldGet(this, _TemperatureCommand_regex, "f"));
44
+ if (!matches)
45
+ throw new errors_1.UnexpectedParseError("Match not found");
46
+ metar.temperature = converter.convertTemperature(matches[1]);
47
+ metar.dewPoint = converter.convertTemperature(matches[2]);
48
+ }
49
+ }
50
+ exports.TemperatureCommand = TemperatureCommand;
51
+ _TemperatureCommand_regex = new WeakMap();
@@ -1,30 +1,9 @@
1
1
  import { IMetar } from "../model/model";
2
- interface ICommand {
2
+ export interface ICommand {
3
3
  canParse(str: string): boolean;
4
4
  execute(metar: IMetar, str: string): void;
5
5
  }
6
- export declare class AltimeterCommand implements ICommand {
7
- #private;
8
- canParse(input: string): boolean;
9
- execute(metar: IMetar, input: string): void;
10
- }
11
- export declare class AltimeterMercuryCommand implements ICommand {
12
- #private;
13
- canParse(input: string): boolean;
14
- execute(metar: IMetar, input: string): void;
15
- }
16
- export declare class RunwayCommand implements ICommand {
17
- #private;
18
- canParse(input: string): boolean;
19
- execute(metar: IMetar, input: string): void;
20
- }
21
- export declare class TemperatureCommand implements ICommand {
22
- #private;
23
- canParse(input: string): boolean;
24
- execute(metar: IMetar, input: string): void;
25
- }
26
6
  export declare class CommandSupplier {
27
7
  #private;
28
8
  get(input: string): ICommand | undefined;
29
9
  }
30
- export {};
@@ -1,131 +1,27 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || function (mod) {
19
- if (mod && mod.__esModule) return mod;
20
- var result = {};
21
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
- __setModuleDefault(result, mod);
23
- return result;
24
- };
25
2
  var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
26
3
  if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
27
4
  if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
28
5
  return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
29
6
  };
30
- var _AltimeterCommand_regex, _AltimeterMercuryCommand_regex, _RunwayCommand_genericRegex, _RunwayCommand_runwayMaxRangeRegex, _RunwayCommand_runwayRegex, _TemperatureCommand_regex, _CommandSupplier_commands;
7
+ var _CommandSupplier_commands;
31
8
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.CommandSupplier = exports.TemperatureCommand = exports.RunwayCommand = exports.AltimeterMercuryCommand = exports.AltimeterCommand = void 0;
33
- const converter = __importStar(require("../commons/converter"));
34
- const errors_1 = require("../commons/errors");
35
- class AltimeterCommand {
36
- constructor() {
37
- _AltimeterCommand_regex.set(this, /^Q(\d{4})$/);
38
- }
39
- canParse(input) {
40
- return __classPrivateFieldGet(this, _AltimeterCommand_regex, "f").test(input);
41
- }
42
- execute(metar, input) {
43
- const matches = input.match(__classPrivateFieldGet(this, _AltimeterCommand_regex, "f"));
44
- if (!matches)
45
- throw new errors_1.UnexpectedParseError("Match not found");
46
- metar.altimeter = Math.trunc(+matches[1]);
47
- }
48
- }
49
- exports.AltimeterCommand = AltimeterCommand;
50
- _AltimeterCommand_regex = new WeakMap();
51
- class AltimeterMercuryCommand {
52
- constructor() {
53
- _AltimeterMercuryCommand_regex.set(this, /^A(\d{4})$/);
54
- }
55
- canParse(input) {
56
- return __classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f").test(input);
57
- }
58
- execute(metar, input) {
59
- const matches = input.match(__classPrivateFieldGet(this, _AltimeterMercuryCommand_regex, "f"));
60
- if (!matches)
61
- throw new errors_1.UnexpectedParseError("Match not found");
62
- const mercury = +matches[1] / 100;
63
- metar.altimeter = Math.trunc(converter.convertInchesMercuryToPascal(mercury));
64
- }
65
- }
66
- exports.AltimeterMercuryCommand = AltimeterMercuryCommand;
67
- _AltimeterMercuryCommand_regex = new WeakMap();
68
- class RunwayCommand {
69
- constructor() {
70
- _RunwayCommand_genericRegex.set(this, /^(R\d{2}\w?\/)/);
71
- _RunwayCommand_runwayMaxRangeRegex.set(this, /^R(\d{2}\w?)\/(\d{4})V(\d{3})(\w{0,2})/);
72
- _RunwayCommand_runwayRegex.set(this, /^R(\d{2}\w?)\/(\w)?(\d{4})(\w{0,2})$/);
73
- }
74
- canParse(input) {
75
- return __classPrivateFieldGet(this, _RunwayCommand_genericRegex, "f").test(input);
76
- }
77
- execute(metar, input) {
78
- const matches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayRegex, "f"));
79
- // TODO idk if this matches super well...
80
- if (matches) {
81
- metar.runwaysInfo.push({
82
- name: matches[1],
83
- minRange: +matches[3],
84
- trend: matches[4],
85
- });
86
- }
87
- const maxRangeMatches = input.match(__classPrivateFieldGet(this, _RunwayCommand_runwayMaxRangeRegex, "f"));
88
- if (maxRangeMatches) {
89
- metar.runwaysInfo.push({
90
- name: maxRangeMatches[1],
91
- minRange: +maxRangeMatches[2],
92
- maxRange: +maxRangeMatches[3],
93
- trend: maxRangeMatches[4],
94
- });
95
- }
96
- }
97
- }
98
- exports.RunwayCommand = RunwayCommand;
99
- _RunwayCommand_genericRegex = new WeakMap(), _RunwayCommand_runwayMaxRangeRegex = new WeakMap(), _RunwayCommand_runwayRegex = new WeakMap();
100
- class TemperatureCommand {
101
- constructor() {
102
- _TemperatureCommand_regex.set(this, /^(M?\d{2})\/(M?\d{2})$/);
103
- }
104
- canParse(input) {
105
- return __classPrivateFieldGet(this, _TemperatureCommand_regex, "f").test(input);
106
- }
107
- execute(metar, input) {
108
- const matches = input.match(__classPrivateFieldGet(this, _TemperatureCommand_regex, "f"));
109
- if (!matches)
110
- throw new errors_1.UnexpectedParseError("Match not found");
111
- metar.temperature = converter.convertTemperature(matches[1]);
112
- metar.dewPoint = converter.convertTemperature(matches[2]);
113
- }
114
- }
115
- exports.TemperatureCommand = TemperatureCommand;
116
- _TemperatureCommand_regex = new WeakMap();
9
+ exports.CommandSupplier = void 0;
10
+ const AltimeterCommand_1 = require("./metar/AltimeterCommand");
11
+ const AltimeterMercuryCommand_1 = require("./metar/AltimeterMercuryCommand");
12
+ const RunwayCommand_1 = require("./metar/RunwayCommand");
13
+ const TemperatureCommand_1 = require("./metar/TemperatureCommand");
117
14
  class CommandSupplier {
118
15
  constructor() {
119
16
  _CommandSupplier_commands.set(this, [
120
- new RunwayCommand(),
121
- new TemperatureCommand(),
122
- new AltimeterCommand(),
123
- new AltimeterMercuryCommand(),
17
+ new RunwayCommand_1.RunwayCommand(),
18
+ new TemperatureCommand_1.TemperatureCommand(),
19
+ new AltimeterCommand_1.AltimeterCommand(),
20
+ new AltimeterMercuryCommand_1.AltimeterMercuryCommand(),
124
21
  ]);
125
22
  }
126
23
  get(input) {
127
- for (let i = 0; i < __classPrivateFieldGet(this, _CommandSupplier_commands, "f").length; i++) {
128
- const command = __classPrivateFieldGet(this, _CommandSupplier_commands, "f")[i];
24
+ for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands, "f")) {
129
25
  if (command.canParse(input))
130
26
  return command;
131
27
  }
@@ -0,0 +1,18 @@
1
+ import { IBaseRemark, RemarkType, Remark } from "../remark";
2
+ import { Command } from "./Command";
3
+ export interface ICeilingHeightRemark extends IBaseRemark {
4
+ type: RemarkType.CeilingHeight;
5
+ /**
6
+ * Ceiling min height (varying between min and max) above ground level
7
+ */
8
+ min: number;
9
+ /**
10
+ * Ceiling max height (varying between min and max) above ground level
11
+ */
12
+ max: number;
13
+ }
14
+ export declare class CeilingHeightCommand extends Command {
15
+ #private;
16
+ canParse(code: string): boolean;
17
+ execute(code: string, remark: Remark[]): [string, Remark[]];
18
+ }