metar-taf-parser 7.0.0 → 7.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.
- package/README.md +4 -0
- package/metar-taf-parser.d.ts +94 -20
- package/metar-taf-parser.js +172 -45
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -175,6 +175,10 @@ function findSeaLevelPressure(remarks: Remark[]): number | undefined {
|
|
|
175
175
|
}
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
+
## Determining flight category, ceiling, etc
|
|
179
|
+
|
|
180
|
+
Because certain abstractions such as flight category and flight ceiling can vary by country, this logic is left up to you to implement. However, if you're looking for somewhere to start, check out the example site (based on United States flight rules) in [example/src/helpers/metarTaf.ts](https://github.com/aeharding/metar-taf-parser/blob/main/example/src/helpers/metarTaf.ts). Feel free to copy - it's MIT licensed.
|
|
181
|
+
|
|
178
182
|
## Development
|
|
179
183
|
|
|
180
184
|
### Example site
|
package/metar-taf-parser.d.ts
CHANGED
|
@@ -275,6 +275,57 @@ declare enum RunwayInfoUnit {
|
|
|
275
275
|
Feet = "FT",
|
|
276
276
|
Meters = "m"
|
|
277
277
|
}
|
|
278
|
+
declare enum IcingIntensity {
|
|
279
|
+
/**
|
|
280
|
+
* Trace Icing or None.
|
|
281
|
+
*
|
|
282
|
+
* Air Force code 0 means a trace of icing.
|
|
283
|
+
* World Meteorological Organization code 0 means no icing
|
|
284
|
+
*/
|
|
285
|
+
None = "0",
|
|
286
|
+
/** Light Mixed Icing. */
|
|
287
|
+
Light = "1",
|
|
288
|
+
/** Light Rime Icing In Cloud. */
|
|
289
|
+
LightRimeIcingCloud = "2",
|
|
290
|
+
/** Light Clear Icing In Precipitation. */
|
|
291
|
+
LightClearIcingPrecipitation = "3",
|
|
292
|
+
/** Moderate Mixed Icing. */
|
|
293
|
+
ModerateMixedIcing = "4",
|
|
294
|
+
/** Moderate Rime Icing In Cloud. */
|
|
295
|
+
ModerateRimeIcingCloud = "5",
|
|
296
|
+
/** Moderate Clear Icing In Precipitation. */
|
|
297
|
+
ModerateClearIcingPrecipitation = "6",
|
|
298
|
+
/** Severe Mixed Icing. */
|
|
299
|
+
SevereMixedIcing = "7",
|
|
300
|
+
/** Severe Rime Icing In Cloud. */
|
|
301
|
+
SevereRimeIcingCloud = "8",
|
|
302
|
+
/** Severe Clear Icing In Precipitation. */
|
|
303
|
+
SevereClearIcingPrecipitation = "9"
|
|
304
|
+
}
|
|
305
|
+
declare enum TurbulenceIntensity {
|
|
306
|
+
/** None. */
|
|
307
|
+
None = "0",
|
|
308
|
+
/** Light turbulence. */
|
|
309
|
+
Light = "1",
|
|
310
|
+
/** Moderate turbulence in clear air, occasional. */
|
|
311
|
+
ModerateClearAirOccasional = "2",
|
|
312
|
+
/** Moderate turbulence in clear air, frequent. */
|
|
313
|
+
ModerateClearAirFrequent = "3",
|
|
314
|
+
/** Moderate turbulence in cloud, occasional. */
|
|
315
|
+
ModerateCloudOccasional = "4",
|
|
316
|
+
/** Moderate turbulence in cloud, frequent. */
|
|
317
|
+
ModerateCloudFrequent = "5",
|
|
318
|
+
/** Severe turbulence in clear air, occasional. */
|
|
319
|
+
SevereClearAirOccasional = "6",
|
|
320
|
+
/** Severe turbulence in clear air, frequent. */
|
|
321
|
+
SevereClearAirFrequent = "7",
|
|
322
|
+
/** Severe turbulence in cloud, occasional. */
|
|
323
|
+
SevereCloudOccasional = "8",
|
|
324
|
+
/** Severe turbulence in cloud, frequent. */
|
|
325
|
+
SevereCloudFrequent = "9",
|
|
326
|
+
/** Extreme turbulence */
|
|
327
|
+
Extreme = "X"
|
|
328
|
+
}
|
|
278
329
|
|
|
279
330
|
declare const _default: {
|
|
280
331
|
CloudQuantity: {
|
|
@@ -1042,22 +1093,6 @@ declare enum RemarkType {
|
|
|
1042
1093
|
}
|
|
1043
1094
|
declare type Remark = IUnknownRemark | IDefaultCommandRemark | ICeilingHeightRemark | ICeilingSecondLocationRemark | IHailSizeRemark | IHourlyMaximumMinimumTemperatureRemark | IHourlyMaximumTemperatureRemark | IHourlyMinimumTemperatureRemark | IHourlyPrecipitationAmountRemark | IHourlyPressureRemark | IHourlyTemperatureDewPointRemark | IIceAccretionRemark | IObscurationRemark | IPrecipitationAmount24HourRemark | IPrecipitationAmount36HourRemark | IPrecipitationAmount36HourRemark | IPrecipitationBegRemark | IPrecipitationBegEndRemark | IPrecipitationEndRemark | IPrevailingVisibilityRemark | ISeaLevelPressureRemark | ISecondLocationVisibilityRemark | ISectorVisibilityRemark | ISmallHailSizeRemark | ISnowDepthRemark | ISnowIncreaseRemark | ISnowPelletsRemark | ISunshineDurationRemark | ISurfaceVisibilityRemark | IThunderStormLocationRemark | IThunderStormLocationMovingRemark | ITornadicActivityBegRemark | ITornadicActivityBegEndRemark | ITornadicActivityEndRemark | ITowerVisibilityRemark | IVariableSkyRemark | IVariableSkyHeightRemark | IVirgaDirectionRemark | IWaterEquivalentSnowRemark | IWindPeakCommandRemark | IWindShiftRemark | IWindShiftFropaRemark;
|
|
1044
1095
|
|
|
1045
|
-
interface ICountry {
|
|
1046
|
-
name: string;
|
|
1047
|
-
}
|
|
1048
|
-
interface IAirport {
|
|
1049
|
-
name: string;
|
|
1050
|
-
city: string;
|
|
1051
|
-
country: string;
|
|
1052
|
-
iata: string;
|
|
1053
|
-
icao: string;
|
|
1054
|
-
latitude: string;
|
|
1055
|
-
longitude: string;
|
|
1056
|
-
altitude: string;
|
|
1057
|
-
timezone: string;
|
|
1058
|
-
dst: boolean;
|
|
1059
|
-
tzDatabase: unknown;
|
|
1060
|
-
}
|
|
1061
1096
|
interface IWind {
|
|
1062
1097
|
speed: number;
|
|
1063
1098
|
direction: string;
|
|
@@ -1122,6 +1157,12 @@ interface ICloud {
|
|
|
1122
1157
|
height?: number;
|
|
1123
1158
|
quantity: CloudQuantity;
|
|
1124
1159
|
type?: CloudType;
|
|
1160
|
+
/**
|
|
1161
|
+
* Very uncommon. For example "FEW025TCU/CB" seen at airport VOTR.
|
|
1162
|
+
*
|
|
1163
|
+
* This property can be ignored in almost all cases.
|
|
1164
|
+
*/
|
|
1165
|
+
secondaryType?: CloudType;
|
|
1125
1166
|
}
|
|
1126
1167
|
interface IFlags {
|
|
1127
1168
|
/**
|
|
@@ -1169,11 +1210,14 @@ interface ITime {
|
|
|
1169
1210
|
}
|
|
1170
1211
|
interface IAbstractWeatherCode extends IAbstractWeatherContainer, ITime {
|
|
1171
1212
|
day?: number;
|
|
1172
|
-
airport?: IAirport;
|
|
1173
1213
|
message: string;
|
|
1174
1214
|
station: string;
|
|
1175
1215
|
trends: IAbstractTrend[];
|
|
1176
1216
|
}
|
|
1217
|
+
interface ITafGroups {
|
|
1218
|
+
turbulence?: ITurbulence[];
|
|
1219
|
+
icing?: IIcing[];
|
|
1220
|
+
}
|
|
1177
1221
|
interface IAbstractWeatherCodeDated extends IAbstractWeatherCode {
|
|
1178
1222
|
issued: Date;
|
|
1179
1223
|
}
|
|
@@ -1188,7 +1232,7 @@ interface IMetar extends IAbstractWeatherCode {
|
|
|
1188
1232
|
*/
|
|
1189
1233
|
trends: IMetarTrend[];
|
|
1190
1234
|
}
|
|
1191
|
-
interface ITAF extends IAbstractWeatherCode {
|
|
1235
|
+
interface ITAF extends IAbstractWeatherCode, ITafGroups {
|
|
1192
1236
|
validity: IValidity;
|
|
1193
1237
|
maxTemperature?: ITemperature;
|
|
1194
1238
|
minTemperature?: ITemperature;
|
|
@@ -1208,7 +1252,7 @@ interface IMetarTrendTime extends ITime {
|
|
|
1208
1252
|
interface IMetarTrend extends IAbstractTrend {
|
|
1209
1253
|
times: IMetarTrendTime[];
|
|
1210
1254
|
}
|
|
1211
|
-
interface IBaseTAFTrend extends IAbstractTrend {
|
|
1255
|
+
interface IBaseTAFTrend extends IAbstractTrend, ITafGroups {
|
|
1212
1256
|
/**
|
|
1213
1257
|
* Will not be found on FM trends. May exist on others.
|
|
1214
1258
|
*
|
|
@@ -1260,6 +1304,36 @@ interface IValidityDated extends IAbstractValidity, IEndValidity {
|
|
|
1260
1304
|
interface IFMValidity extends IAbstractValidity {
|
|
1261
1305
|
startMinutes: number;
|
|
1262
1306
|
}
|
|
1307
|
+
/**
|
|
1308
|
+
* Represents icing in a TAF.
|
|
1309
|
+
*
|
|
1310
|
+
* http://prnfc.org/wp-content/uploads/2016/12/AF-METAR-TAF-Codes.pdf#page=28
|
|
1311
|
+
*
|
|
1312
|
+
* Top of icing = `baseHeight` + `depth`
|
|
1313
|
+
*/
|
|
1314
|
+
interface IIcing {
|
|
1315
|
+
/** The intensity of the icing. */
|
|
1316
|
+
intensity: IcingIntensity;
|
|
1317
|
+
/** The base of the icing layer in feet. */
|
|
1318
|
+
baseHeight: number;
|
|
1319
|
+
/** The icing layer depth in feet. */
|
|
1320
|
+
depth: number;
|
|
1321
|
+
}
|
|
1322
|
+
/**
|
|
1323
|
+
* Represents turbulence in a TAF.
|
|
1324
|
+
*
|
|
1325
|
+
* http://prnfc.org/wp-content/uploads/2016/12/AF-METAR-TAF-Codes.pdf#page=29
|
|
1326
|
+
*
|
|
1327
|
+
* Top of icing = `baseHeight` + `depth`
|
|
1328
|
+
*/
|
|
1329
|
+
interface ITurbulence {
|
|
1330
|
+
/** The intensity of the turbulence. */
|
|
1331
|
+
intensity: TurbulenceIntensity;
|
|
1332
|
+
/** The base limit of the turbulence layer in feet. */
|
|
1333
|
+
baseHeight: number;
|
|
1334
|
+
/** The turbulence layer depth in feet. */
|
|
1335
|
+
depth: number;
|
|
1336
|
+
}
|
|
1263
1337
|
|
|
1264
1338
|
interface IMetarDated extends IMetar {
|
|
1265
1339
|
issued: Date;
|
|
@@ -1388,4 +1462,4 @@ declare function parseTAF(rawTAF: string, options?: IMetarTAFParserOptions): ITA
|
|
|
1388
1462
|
declare function parseTAF(rawTAF: string, options?: IMetarTAFParserOptionsDated): ITAFDated;
|
|
1389
1463
|
declare function parseTAFAsForecast(rawTAF: string, options: IMetarTAFParserOptionsDated): IForecastContainer;
|
|
1390
1464
|
|
|
1391
|
-
export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, Distance, DistanceUnit, Forecast, IAbstractTrend, IAbstractValidity, IAbstractWeatherCode, IAbstractWeatherCodeDated, IAbstractWeatherContainer,
|
|
1465
|
+
export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, Distance, DistanceUnit, Forecast, IAbstractTrend, IAbstractValidity, IAbstractWeatherCode, IAbstractWeatherCodeDated, IAbstractWeatherContainer, IBaseRemark, IBaseTAFTrend, ICeilingHeightRemark, ICeilingSecondLocationRemark, ICloud, ICompositeForecast, IEndValidity, IFMValidity, IFlags, IForecastContainer, IHourlyMaximumMinimumTemperatureRemark, IHourlyMaximumTemperatureRemark, IHourlyMinimumTemperatureRemark, IHourlyPrecipitationAmountRemark, IHourlyPressureRemark, IHourlyTemperatureDewPointRemark, IIceAccretionRemark, IIcing, IMetar, IMetarTAFParserOptions, IMetarTAFParserOptionsDated, IMetarTrend, IMetarTrendTime, IObscurationRemark, IPrecipitationAmount24HourRemark, IPrecipitationAmount36HourRemark, IPrecipitationBegEndRemark, IPrevailingVisibilityRemark, IRunwayInfo, ISeaLevelPressureRemark, ISecondLocationVisibilityRemark, ISectorVisibilityRemark, ISmallHailSizeRemark, ISnowIncreaseRemark, ISnowPelletsRemark, ISunshineDurationRemark, ISurfaceVisibilityRemark, ITAF, ITAFDated, ITafGroups, ITemperature, ITemperatureDated, IThunderStormLocationMovingRemark, IThunderStormLocationRemark, ITime, ITornadicActivityBegEndRemark, ITornadicActivityBegRemark, ITornadicActivityEndRemark, ITowerVisibilityRemark, ITurbulence, IUnknownRemark, IValidity, IValidityDated, IVariableSkyHeightRemark, IVariableSkyRemark, IVirgaDirectionRemark, IWaterEquivalentSnowRemark, IWeatherCondition, IWind, IWindPeakCommandRemark, IWindShear, IWindShiftFropaRemark, IcingIntensity, Intensity, InvalidWeatherStatementError, Locale, ParseError, Phenomenon, Remark, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TAFTrend, TAFTrendDated, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, Visibility, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
|
package/metar-taf-parser.js
CHANGED
|
@@ -473,6 +473,59 @@ var RunwayInfoUnit;
|
|
|
473
473
|
RunwayInfoUnit["Feet"] = "FT";
|
|
474
474
|
RunwayInfoUnit["Meters"] = "m";
|
|
475
475
|
})(RunwayInfoUnit || (RunwayInfoUnit = {}));
|
|
476
|
+
var IcingIntensity;
|
|
477
|
+
(function (IcingIntensity) {
|
|
478
|
+
/**
|
|
479
|
+
* Trace Icing or None.
|
|
480
|
+
*
|
|
481
|
+
* Air Force code 0 means a trace of icing.
|
|
482
|
+
* World Meteorological Organization code 0 means no icing
|
|
483
|
+
*/
|
|
484
|
+
IcingIntensity["None"] = "0";
|
|
485
|
+
/** Light Mixed Icing. */
|
|
486
|
+
IcingIntensity["Light"] = "1";
|
|
487
|
+
/** Light Rime Icing In Cloud. */
|
|
488
|
+
IcingIntensity["LightRimeIcingCloud"] = "2";
|
|
489
|
+
/** Light Clear Icing In Precipitation. */
|
|
490
|
+
IcingIntensity["LightClearIcingPrecipitation"] = "3";
|
|
491
|
+
/** Moderate Mixed Icing. */
|
|
492
|
+
IcingIntensity["ModerateMixedIcing"] = "4";
|
|
493
|
+
/** Moderate Rime Icing In Cloud. */
|
|
494
|
+
IcingIntensity["ModerateRimeIcingCloud"] = "5";
|
|
495
|
+
/** Moderate Clear Icing In Precipitation. */
|
|
496
|
+
IcingIntensity["ModerateClearIcingPrecipitation"] = "6";
|
|
497
|
+
/** Severe Mixed Icing. */
|
|
498
|
+
IcingIntensity["SevereMixedIcing"] = "7";
|
|
499
|
+
/** Severe Rime Icing In Cloud. */
|
|
500
|
+
IcingIntensity["SevereRimeIcingCloud"] = "8";
|
|
501
|
+
/** Severe Clear Icing In Precipitation. */
|
|
502
|
+
IcingIntensity["SevereClearIcingPrecipitation"] = "9";
|
|
503
|
+
})(IcingIntensity || (IcingIntensity = {}));
|
|
504
|
+
var TurbulenceIntensity;
|
|
505
|
+
(function (TurbulenceIntensity) {
|
|
506
|
+
/** None. */
|
|
507
|
+
TurbulenceIntensity["None"] = "0";
|
|
508
|
+
/** Light turbulence. */
|
|
509
|
+
TurbulenceIntensity["Light"] = "1";
|
|
510
|
+
/** Moderate turbulence in clear air, occasional. */
|
|
511
|
+
TurbulenceIntensity["ModerateClearAirOccasional"] = "2";
|
|
512
|
+
/** Moderate turbulence in clear air, frequent. */
|
|
513
|
+
TurbulenceIntensity["ModerateClearAirFrequent"] = "3";
|
|
514
|
+
/** Moderate turbulence in cloud, occasional. */
|
|
515
|
+
TurbulenceIntensity["ModerateCloudOccasional"] = "4";
|
|
516
|
+
/** Moderate turbulence in cloud, frequent. */
|
|
517
|
+
TurbulenceIntensity["ModerateCloudFrequent"] = "5";
|
|
518
|
+
/** Severe turbulence in clear air, occasional. */
|
|
519
|
+
TurbulenceIntensity["SevereClearAirOccasional"] = "6";
|
|
520
|
+
/** Severe turbulence in clear air, frequent. */
|
|
521
|
+
TurbulenceIntensity["SevereClearAirFrequent"] = "7";
|
|
522
|
+
/** Severe turbulence in cloud, occasional. */
|
|
523
|
+
TurbulenceIntensity["SevereCloudOccasional"] = "8";
|
|
524
|
+
/** Severe turbulence in cloud, frequent. */
|
|
525
|
+
TurbulenceIntensity["SevereCloudFrequent"] = "9";
|
|
526
|
+
/** Extreme turbulence */
|
|
527
|
+
TurbulenceIntensity["Extreme"] = "X";
|
|
528
|
+
})(TurbulenceIntensity || (TurbulenceIntensity = {}));
|
|
476
529
|
|
|
477
530
|
function degreesToCardinal(input) {
|
|
478
531
|
const degrees = +input;
|
|
@@ -1741,7 +1794,7 @@ function isWeatherConditionValid(weather) {
|
|
|
1741
1794
|
weather.descriptive == Descriptive.SHOWERS));
|
|
1742
1795
|
}
|
|
1743
1796
|
|
|
1744
|
-
var _CloudCommand_cloudRegex, _MainVisibilityCommand_regex, _WindCommand_regex, _WindVariationCommand_regex, _WindShearCommand_regex, _VerticalVisibilityCommand_regex, _MinimalVisibilityCommand_regex, _MainVisibilityNauticalMilesCommand_regex, _CommandSupplier_commands$
|
|
1797
|
+
var _CloudCommand_cloudRegex, _MainVisibilityCommand_regex, _WindCommand_regex, _WindVariationCommand_regex, _WindShearCommand_regex, _VerticalVisibilityCommand_regex, _MinimalVisibilityCommand_regex, _MainVisibilityNauticalMilesCommand_regex, _CommandSupplier_commands$2;
|
|
1745
1798
|
/**
|
|
1746
1799
|
* This function creates a wind element.
|
|
1747
1800
|
* @param wind The wind object
|
|
@@ -1761,18 +1814,17 @@ function makeWind(direction, speed, gust, unit) {
|
|
|
1761
1814
|
}
|
|
1762
1815
|
class CloudCommand {
|
|
1763
1816
|
constructor() {
|
|
1764
|
-
_CloudCommand_cloudRegex.set(this, /^([A-Z]{3})(\d{3})?([A-Z]{2,3})?$/);
|
|
1817
|
+
_CloudCommand_cloudRegex.set(this, /^([A-Z]{3})(?:\/{3}|(\d{3}))?(?:\/{3}|(?:([A-Z]{2,3})(?:\/([A-Z]{2,3}))?))?$/);
|
|
1765
1818
|
}
|
|
1766
1819
|
parse(cloudString) {
|
|
1767
1820
|
const m = cloudString.match(__classPrivateFieldGet(this, _CloudCommand_cloudRegex, "f"));
|
|
1768
1821
|
if (!m)
|
|
1769
1822
|
return;
|
|
1770
|
-
const quantity =
|
|
1823
|
+
const quantity = as(m[1], CloudQuantity);
|
|
1771
1824
|
const height = 100 * +m[2] || undefined;
|
|
1772
|
-
const type =
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
return { quantity, height, type };
|
|
1825
|
+
const type = m[3] ? as(m[3], CloudType) : undefined;
|
|
1826
|
+
const secondaryType = m[4] ? as(m[4], CloudType) : undefined;
|
|
1827
|
+
return { quantity, height, type, secondaryType };
|
|
1776
1828
|
}
|
|
1777
1829
|
execute(container, cloudString) {
|
|
1778
1830
|
const cloud = this.parse(cloudString);
|
|
@@ -1811,7 +1863,7 @@ class MainVisibilityCommand {
|
|
|
1811
1863
|
_MainVisibilityCommand_regex = new WeakMap();
|
|
1812
1864
|
class WindCommand {
|
|
1813
1865
|
constructor() {
|
|
1814
|
-
_WindCommand_regex.set(this, /^(VRB
|
|
1866
|
+
_WindCommand_regex.set(this, /^(VRB|[0-3]\d{2})(\d{2})G?(\d{2})?(KT|MPS|KM\/H)?/);
|
|
1815
1867
|
}
|
|
1816
1868
|
canParse(windString) {
|
|
1817
1869
|
return __classPrivateFieldGet(this, _WindCommand_regex, "f").test(windString);
|
|
@@ -1924,9 +1976,9 @@ class MainVisibilityNauticalMilesCommand {
|
|
|
1924
1976
|
}
|
|
1925
1977
|
}
|
|
1926
1978
|
_MainVisibilityNauticalMilesCommand_regex = new WeakMap();
|
|
1927
|
-
class CommandSupplier$
|
|
1979
|
+
class CommandSupplier$2 {
|
|
1928
1980
|
constructor() {
|
|
1929
|
-
_CommandSupplier_commands$
|
|
1981
|
+
_CommandSupplier_commands$2.set(this, [
|
|
1930
1982
|
new WindShearCommand(),
|
|
1931
1983
|
new WindCommand(),
|
|
1932
1984
|
new WindVariationCommand(),
|
|
@@ -1938,13 +1990,13 @@ class CommandSupplier$1 {
|
|
|
1938
1990
|
]);
|
|
1939
1991
|
}
|
|
1940
1992
|
get(input) {
|
|
1941
|
-
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands$
|
|
1993
|
+
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands$2, "f")) {
|
|
1942
1994
|
if (command.canParse(input))
|
|
1943
1995
|
return command;
|
|
1944
1996
|
}
|
|
1945
1997
|
}
|
|
1946
1998
|
}
|
|
1947
|
-
_CommandSupplier_commands$
|
|
1999
|
+
_CommandSupplier_commands$2 = new WeakMap();
|
|
1948
2000
|
|
|
1949
2001
|
var _AltimeterCommand_regex;
|
|
1950
2002
|
class AltimeterCommand {
|
|
@@ -2048,16 +2100,76 @@ class TemperatureCommand {
|
|
|
2048
2100
|
}
|
|
2049
2101
|
_TemperatureCommand_regex = new WeakMap();
|
|
2050
2102
|
|
|
2051
|
-
var _CommandSupplier_commands;
|
|
2052
|
-
class CommandSupplier {
|
|
2103
|
+
var _CommandSupplier_commands$1;
|
|
2104
|
+
class CommandSupplier$1 {
|
|
2053
2105
|
constructor() {
|
|
2054
|
-
_CommandSupplier_commands.set(this, [
|
|
2106
|
+
_CommandSupplier_commands$1.set(this, [
|
|
2055
2107
|
new RunwayCommand(),
|
|
2056
2108
|
new TemperatureCommand(),
|
|
2057
2109
|
new AltimeterCommand(),
|
|
2058
2110
|
new AltimeterMercuryCommand(),
|
|
2059
2111
|
]);
|
|
2060
2112
|
}
|
|
2113
|
+
get(input) {
|
|
2114
|
+
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands$1, "f")) {
|
|
2115
|
+
if (command.canParse(input))
|
|
2116
|
+
return command;
|
|
2117
|
+
}
|
|
2118
|
+
}
|
|
2119
|
+
}
|
|
2120
|
+
_CommandSupplier_commands$1 = new WeakMap();
|
|
2121
|
+
|
|
2122
|
+
var _IcingCommand_regex;
|
|
2123
|
+
class IcingCommand {
|
|
2124
|
+
constructor() {
|
|
2125
|
+
_IcingCommand_regex.set(this, /^6(\d)(\d{3})(\d)$/);
|
|
2126
|
+
}
|
|
2127
|
+
canParse(input) {
|
|
2128
|
+
return __classPrivateFieldGet(this, _IcingCommand_regex, "f").test(input);
|
|
2129
|
+
}
|
|
2130
|
+
execute(container, input) {
|
|
2131
|
+
const matches = input.match(__classPrivateFieldGet(this, _IcingCommand_regex, "f"));
|
|
2132
|
+
if (!matches)
|
|
2133
|
+
throw new UnexpectedParseError("Match not found");
|
|
2134
|
+
if (!container.icing)
|
|
2135
|
+
container.icing = [];
|
|
2136
|
+
container.icing.push({
|
|
2137
|
+
intensity: as(matches[1], IcingIntensity),
|
|
2138
|
+
baseHeight: +matches[2] * 100,
|
|
2139
|
+
depth: +matches[3] * 1000,
|
|
2140
|
+
});
|
|
2141
|
+
}
|
|
2142
|
+
}
|
|
2143
|
+
_IcingCommand_regex = new WeakMap();
|
|
2144
|
+
|
|
2145
|
+
var _TurbulenceCommand_regex;
|
|
2146
|
+
class TurbulenceCommand {
|
|
2147
|
+
constructor() {
|
|
2148
|
+
_TurbulenceCommand_regex.set(this, /^5(\d|X)(\d{3})(\d)$/);
|
|
2149
|
+
}
|
|
2150
|
+
canParse(input) {
|
|
2151
|
+
return __classPrivateFieldGet(this, _TurbulenceCommand_regex, "f").test(input);
|
|
2152
|
+
}
|
|
2153
|
+
execute(container, input) {
|
|
2154
|
+
const matches = input.match(__classPrivateFieldGet(this, _TurbulenceCommand_regex, "f"));
|
|
2155
|
+
if (!matches)
|
|
2156
|
+
throw new UnexpectedParseError("Match not found");
|
|
2157
|
+
if (!container.turbulence)
|
|
2158
|
+
container.turbulence = [];
|
|
2159
|
+
container.turbulence.push({
|
|
2160
|
+
intensity: as(matches[1], TurbulenceIntensity),
|
|
2161
|
+
baseHeight: +matches[2] * 100,
|
|
2162
|
+
depth: +matches[3] * 1000,
|
|
2163
|
+
});
|
|
2164
|
+
}
|
|
2165
|
+
}
|
|
2166
|
+
_TurbulenceCommand_regex = new WeakMap();
|
|
2167
|
+
|
|
2168
|
+
var _CommandSupplier_commands;
|
|
2169
|
+
class CommandSupplier {
|
|
2170
|
+
constructor() {
|
|
2171
|
+
_CommandSupplier_commands.set(this, [new TurbulenceCommand(), new IcingCommand()]);
|
|
2172
|
+
}
|
|
2061
2173
|
get(input) {
|
|
2062
2174
|
for (const command of __classPrivateFieldGet(this, _CommandSupplier_commands, "f")) {
|
|
2063
2175
|
if (command.canParse(input))
|
|
@@ -2067,7 +2179,7 @@ class CommandSupplier {
|
|
|
2067
2179
|
}
|
|
2068
2180
|
_CommandSupplier_commands = new WeakMap();
|
|
2069
2181
|
|
|
2070
|
-
var _AbstractParser_INTENSITY_REGEX, _AbstractParser_CAVOK, _AbstractParser_commonSupplier, _MetarParser_commandSupplier, _TAFParser_validityPattern, _RemarkParser_supplier;
|
|
2182
|
+
var _AbstractParser_INTENSITY_REGEX, _AbstractParser_CAVOK, _AbstractParser_commonSupplier, _MetarParser_commandSupplier, _TAFParser_commandSupplier, _TAFParser_validityPattern, _RemarkParser_supplier;
|
|
2071
2183
|
/**
|
|
2072
2184
|
* Parses the delivery time of a METAR/TAF
|
|
2073
2185
|
* @param abstractWeatherCode The TAF or METAR object
|
|
@@ -2171,7 +2283,7 @@ class AbstractParser {
|
|
|
2171
2283
|
// #TOKENIZE_REGEX = /\s((?=\d\/\dSM)(?<!\s\d\s)|(?!\d\/\dSM))|=/;
|
|
2172
2284
|
_AbstractParser_INTENSITY_REGEX.set(this, /^(-|\+|VC)/);
|
|
2173
2285
|
_AbstractParser_CAVOK.set(this, "CAVOK");
|
|
2174
|
-
_AbstractParser_commonSupplier.set(this, new CommandSupplier$
|
|
2286
|
+
_AbstractParser_commonSupplier.set(this, new CommandSupplier$2());
|
|
2175
2287
|
}
|
|
2176
2288
|
parseWeatherCondition(input) {
|
|
2177
2289
|
let intensity;
|
|
@@ -2240,7 +2352,14 @@ class AbstractParser {
|
|
|
2240
2352
|
}
|
|
2241
2353
|
const command = __classPrivateFieldGet(this, _AbstractParser_commonSupplier, "f").get(input);
|
|
2242
2354
|
if (command) {
|
|
2243
|
-
|
|
2355
|
+
try {
|
|
2356
|
+
return command.execute(abstractWeatherContainer, input);
|
|
2357
|
+
}
|
|
2358
|
+
catch (error) {
|
|
2359
|
+
if (error instanceof CommandExecutionError)
|
|
2360
|
+
return false;
|
|
2361
|
+
throw error;
|
|
2362
|
+
}
|
|
2244
2363
|
}
|
|
2245
2364
|
const weatherCondition = this.parseWeatherCondition(input);
|
|
2246
2365
|
if (isWeatherConditionValid(weatherCondition)) {
|
|
@@ -2256,7 +2375,7 @@ class MetarParser extends AbstractParser {
|
|
|
2256
2375
|
super(...arguments);
|
|
2257
2376
|
this.AT = "AT";
|
|
2258
2377
|
this.TL = "TL";
|
|
2259
|
-
_MetarParser_commandSupplier.set(this, new CommandSupplier());
|
|
2378
|
+
_MetarParser_commandSupplier.set(this, new CommandSupplier$1());
|
|
2260
2379
|
}
|
|
2261
2380
|
/**
|
|
2262
2381
|
* Parses a trend of a metar
|
|
@@ -2354,6 +2473,7 @@ class TAFParser extends AbstractParser {
|
|
|
2354
2473
|
this.PROB = "PROB";
|
|
2355
2474
|
this.TX = "TX";
|
|
2356
2475
|
this.TN = "TN";
|
|
2476
|
+
_TAFParser_commandSupplier.set(this, new CommandSupplier());
|
|
2357
2477
|
_TAFParser_validityPattern.set(this, /^\d{4}\/\d{4}$/);
|
|
2358
2478
|
}
|
|
2359
2479
|
/**
|
|
@@ -2406,13 +2526,17 @@ class TAFParser extends AbstractParser {
|
|
|
2406
2526
|
};
|
|
2407
2527
|
for (let i = index + 1; i < lines[0].length; i++) {
|
|
2408
2528
|
const token = lines[0][i];
|
|
2529
|
+
const tafCommand = __classPrivateFieldGet(this, _TAFParser_commandSupplier, "f").get(token);
|
|
2409
2530
|
if (token == this.RMK) {
|
|
2410
2531
|
parseRemark(taf, lines[0], i, this.locale);
|
|
2411
2532
|
break;
|
|
2412
2533
|
}
|
|
2534
|
+
else if (tafCommand) {
|
|
2535
|
+
tafCommand.execute(taf, token);
|
|
2536
|
+
}
|
|
2413
2537
|
else {
|
|
2414
|
-
parseFlags(taf, token);
|
|
2415
2538
|
this.generalParse(taf, token);
|
|
2539
|
+
parseFlags(taf, token);
|
|
2416
2540
|
}
|
|
2417
2541
|
}
|
|
2418
2542
|
const minMaxTemperatureLines = [
|
|
@@ -2537,6 +2661,7 @@ class TAFParser extends AbstractParser {
|
|
|
2537
2661
|
*/
|
|
2538
2662
|
parseTrend(index, line, trend) {
|
|
2539
2663
|
for (let i = index; i < line.length; i++) {
|
|
2664
|
+
const tafCommand = __classPrivateFieldGet(this, _TAFParser_commandSupplier, "f").get(line[i]);
|
|
2540
2665
|
if (line[i] === this.RMK) {
|
|
2541
2666
|
parseRemark(trend, line, i, this.locale);
|
|
2542
2667
|
break;
|
|
@@ -2544,6 +2669,9 @@ class TAFParser extends AbstractParser {
|
|
|
2544
2669
|
// already parsed
|
|
2545
2670
|
else if (__classPrivateFieldGet(this, _TAFParser_validityPattern, "f").test(line[i]))
|
|
2546
2671
|
continue;
|
|
2672
|
+
else if (tafCommand) {
|
|
2673
|
+
tafCommand.execute(trend, line[i]);
|
|
2674
|
+
}
|
|
2547
2675
|
else
|
|
2548
2676
|
super.generalParse(trend, line[i]);
|
|
2549
2677
|
}
|
|
@@ -2556,7 +2684,7 @@ class TAFParser extends AbstractParser {
|
|
|
2556
2684
|
};
|
|
2557
2685
|
}
|
|
2558
2686
|
}
|
|
2559
|
-
_TAFParser_validityPattern = new WeakMap();
|
|
2687
|
+
_TAFParser_commandSupplier = new WeakMap(), _TAFParser_validityPattern = new WeakMap();
|
|
2560
2688
|
class RemarkParser {
|
|
2561
2689
|
constructor(locale) {
|
|
2562
2690
|
this.locale = locale;
|
|
@@ -2592,7 +2720,7 @@ _RemarkParser_supplier = new WeakMap();
|
|
|
2592
2720
|
* @param minute Minute (from the report)
|
|
2593
2721
|
* @returns
|
|
2594
2722
|
*/
|
|
2595
|
-
function
|
|
2723
|
+
function determineReportDate(date, day, hour, minute = 0) {
|
|
2596
2724
|
// Some TAF reports do not include a delivery time
|
|
2597
2725
|
if (day == null || hour == null)
|
|
2598
2726
|
return date;
|
|
@@ -2608,17 +2736,6 @@ function determineReportIssuedDate(date, day, hour, minute) {
|
|
|
2608
2736
|
}))
|
|
2609
2737
|
.sort((a, b) => a.difference - b.difference)[0].date;
|
|
2610
2738
|
}
|
|
2611
|
-
function getReportDate(issued, day, hour, minute = 0) {
|
|
2612
|
-
let date = new Date(issued);
|
|
2613
|
-
if (day < date.getUTCDate()) {
|
|
2614
|
-
date = addMonthsUTC(date, 1);
|
|
2615
|
-
}
|
|
2616
|
-
date.setUTCDate(day);
|
|
2617
|
-
date.setUTCHours(hour);
|
|
2618
|
-
if (minute != null)
|
|
2619
|
-
date.setUTCMinutes(minute);
|
|
2620
|
-
return date;
|
|
2621
|
-
}
|
|
2622
2739
|
function setDateComponents(date, day, hour, minute) {
|
|
2623
2740
|
date.setUTCDate(day);
|
|
2624
2741
|
date.setUTCHours(hour);
|
|
@@ -2641,30 +2758,30 @@ function addMonthsUTC(date, count) {
|
|
|
2641
2758
|
function metarDatesHydrator(report, date) {
|
|
2642
2759
|
return {
|
|
2643
2760
|
...report,
|
|
2644
|
-
issued:
|
|
2761
|
+
issued: determineReportDate(date, report.day, report.hour, report.minute),
|
|
2645
2762
|
};
|
|
2646
2763
|
}
|
|
2647
2764
|
|
|
2648
2765
|
function tafDatesHydrator(report, date) {
|
|
2649
|
-
const issued =
|
|
2766
|
+
const issued = determineReportDate(date, report.day, report.hour, report.minute);
|
|
2650
2767
|
return {
|
|
2651
2768
|
...report,
|
|
2652
2769
|
issued,
|
|
2653
2770
|
validity: {
|
|
2654
2771
|
...report.validity,
|
|
2655
|
-
start:
|
|
2656
|
-
end:
|
|
2772
|
+
start: determineReportDate(issued, report.validity.startDay, report.validity.startHour),
|
|
2773
|
+
end: determineReportDate(issued, report.validity.endDay, report.validity.endHour),
|
|
2657
2774
|
},
|
|
2658
2775
|
minTemperature: report.minTemperature
|
|
2659
2776
|
? {
|
|
2660
2777
|
...report.minTemperature,
|
|
2661
|
-
date:
|
|
2778
|
+
date: determineReportDate(issued, report.minTemperature.day, report.minTemperature.hour),
|
|
2662
2779
|
}
|
|
2663
2780
|
: undefined,
|
|
2664
2781
|
maxTemperature: report.maxTemperature
|
|
2665
2782
|
? {
|
|
2666
2783
|
...report.maxTemperature,
|
|
2667
|
-
date:
|
|
2784
|
+
date: determineReportDate(issued, report.maxTemperature.day, report.maxTemperature.hour),
|
|
2668
2785
|
}
|
|
2669
2786
|
: undefined,
|
|
2670
2787
|
trends: report.trends.map((trend) => ({
|
|
@@ -2674,13 +2791,13 @@ function tafDatesHydrator(report, date) {
|
|
|
2674
2791
|
case WeatherChangeType.FM:
|
|
2675
2792
|
return {
|
|
2676
2793
|
...trend.validity,
|
|
2677
|
-
start:
|
|
2794
|
+
start: determineReportDate(issued, trend.validity.startDay, trend.validity.startHour, trend.validity.startMinutes),
|
|
2678
2795
|
};
|
|
2679
2796
|
default:
|
|
2680
2797
|
return {
|
|
2681
2798
|
...trend.validity,
|
|
2682
|
-
start:
|
|
2683
|
-
end:
|
|
2799
|
+
start: determineReportDate(issued, trend.validity.startDay, trend.validity.startHour),
|
|
2800
|
+
end: determineReportDate(issued, trend.validity.endDay, trend.validity.endHour),
|
|
2684
2801
|
};
|
|
2685
2802
|
}
|
|
2686
2803
|
})(),
|
|
@@ -2692,8 +2809,8 @@ function getForecastFromTAF(taf) {
|
|
|
2692
2809
|
const { trends, wind, visibility, verticalVisibility, windShear, cavok, remark, remarks, clouds, weatherConditions, initialRaw, validity, ...tafWithoutBaseProperties } = taf;
|
|
2693
2810
|
return {
|
|
2694
2811
|
...tafWithoutBaseProperties,
|
|
2695
|
-
start:
|
|
2696
|
-
end:
|
|
2812
|
+
start: determineReportDate(taf.issued, taf.validity.startDay, taf.validity.startHour),
|
|
2813
|
+
end: determineReportDate(taf.issued, taf.validity.endDay, taf.validity.endHour),
|
|
2697
2814
|
forecast: hydrateEndDates([makeInitialForecast(taf), ...taf.trends], taf.validity),
|
|
2698
2815
|
};
|
|
2699
2816
|
}
|
|
@@ -2712,6 +2829,8 @@ function makeInitialForecast(taf) {
|
|
|
2712
2829
|
clouds: taf.clouds,
|
|
2713
2830
|
weatherConditions: taf.weatherConditions,
|
|
2714
2831
|
raw: taf.initialRaw,
|
|
2832
|
+
turbulence: taf.turbulence,
|
|
2833
|
+
icing: taf.icing,
|
|
2715
2834
|
validity: {
|
|
2716
2835
|
// End day/hour are for end of the entire TAF
|
|
2717
2836
|
startDay: taf.validity.startDay,
|
|
@@ -2781,6 +2900,8 @@ function hydrateEndDates(trends, reportValidity) {
|
|
|
2781
2900
|
* it needs to be populated
|
|
2782
2901
|
*/
|
|
2783
2902
|
function hydrateWithPreviousContextIfNeeded(forecast, context) {
|
|
2903
|
+
// BECMG is the only forecast type that inherits old conditions
|
|
2904
|
+
// Anything else starts anew
|
|
2784
2905
|
if (forecast.type !== WeatherChangeType.BECMG || !context)
|
|
2785
2906
|
return forecast;
|
|
2786
2907
|
// Remarks should not be carried over
|
|
@@ -2790,6 +2911,12 @@ function hydrateWithPreviousContextIfNeeded(forecast, context) {
|
|
|
2790
2911
|
// vertical visibility should not be carried over, if clouds exist
|
|
2791
2912
|
if (forecast.clouds.length)
|
|
2792
2913
|
delete context.verticalVisibility;
|
|
2914
|
+
// CAVOK should not propagate if anything other than wind changes
|
|
2915
|
+
if (forecast.clouds.length ||
|
|
2916
|
+
forecast.verticalVisibility ||
|
|
2917
|
+
forecast.weatherConditions.length ||
|
|
2918
|
+
forecast.visibility)
|
|
2919
|
+
delete context.cavok;
|
|
2793
2920
|
forecast = {
|
|
2794
2921
|
...context,
|
|
2795
2922
|
...forecast,
|
|
@@ -2865,4 +2992,4 @@ function parse(rawReport, options, parser, datesHydrator) {
|
|
|
2865
2992
|
}
|
|
2866
2993
|
}
|
|
2867
2994
|
|
|
2868
|
-
export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, DistanceUnit, Intensity, InvalidWeatherStatementError, ParseError, Phenomenon, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TimeIndicator, TimestampOutOfBoundsError, UnexpectedParseError, ValueIndicator, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
|
|
2995
|
+
export { CloudQuantity, CloudType, CommandExecutionError, Descriptive, Direction, DistanceUnit, IcingIntensity, Intensity, InvalidWeatherStatementError, ParseError, Phenomenon, RemarkType, RunwayInfoTrend, RunwayInfoUnit, SpeedUnit, TimeIndicator, TimestampOutOfBoundsError, TurbulenceIntensity, UnexpectedParseError, ValueIndicator, WeatherChangeType, getCompositeForecastForDate, isWeatherConditionValid, parseMetar, parseTAF, parseTAFAsForecast };
|