Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions lib/src/models/change_indicator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ final CHANGE_TRANSLATIONS = <String, String>{
'NOSIG': 'no significant changes',
'BECMG': 'becoming',
'TEMPO': 'temporary',
'FCST': 'forecast',
'PROB30': 'probability 30%',
'PROB40': 'probability 40%',
};
Expand Down
1 change: 1 addition & 0 deletions lib/src/models/clouds.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Map<String, String> SKY_COVER = {
'BKN': 'broken',
'OVC': 'overcast',
'///': 'undefined',
'//': 'undefined',
'VV': 'indefinite ceiling',
};

Expand Down
63 changes: 20 additions & 43 deletions lib/src/models/metar/metar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ class Metar extends Report
MetarWindMixin,
MetarPrevailingMixin,
MetarWeatherMixin,
MetarCloudMixin {
MetarCloudMixin,
PressureMixin,
MetarTemperatureMixin,
MetarWindVariationMixin {
late final int? _year, _month;

// Body groups
MetarWindVariation _windVariation = MetarWindVariation(null, null);
// Body group
MetarMinimumVisibility _minimumVisibility =
MetarMinimumVisibility(null, null);
final _runwayRanges = GroupList<MetarRunwayRange>(3);
MetarTemperatures _temperatures = MetarTemperatures(null, null);
MetarPressure _pressure = MetarPressure(null, null);
MetarRecentWeather _recentWeather = MetarRecentWeather(null, null);
final _windshear = MetarWindshearList();
MetarSeaState _seaState = MetarSeaState(null, null);
Expand All @@ -26,11 +26,14 @@ class Metar extends Report
// Trend groups
final MetarWeatherTrends _weatherTrends = MetarWeatherTrends();

final DateTime? observedAt;

Metar(
String code, {
int? year,
int? month,
bool truncate = false,
this.observedAt,
}) : super(code, truncate) {
_handleSections();

Expand Down Expand Up @@ -64,16 +67,6 @@ class Metar extends Report
/// Get the time of the METAR.
MetarTime get time => _time;

void _handleWindVariation(String group) {
final match = MetarRegExp.WIND_VARIATION.firstMatch(group);
_windVariation = MetarWindVariation(group, match);

_concatenateString(_windVariation);
}

/// Get the wind variation directions of the METAR.
MetarWindVariation get windVariation => _windVariation;

void _handleMinimumVisibility(String group) {
final match = MetarRegExp.VISIBILITY.firstMatch(group);
_minimumVisibility = MetarMinimumVisibility(group, match);
Expand All @@ -95,26 +88,6 @@ class Metar extends Report
/// Get the runway ranges data of the METAR if provided.
GroupList<MetarRunwayRange> get runwayRanges => _runwayRanges;

void _handleTemperatures(String group) {
final match = MetarRegExp.TEMPERATURES.firstMatch(group);
_temperatures = MetarTemperatures(group, match);

_concatenateString(_temperatures);
}

/// Get the temperatures data of the METAR.
MetarTemperatures get temperatures => _temperatures;

void _handlePressure(String group) {
final match = MetarRegExp.PRESSURE.firstMatch(group);
_pressure = MetarPressure(group, match);

_concatenateString(_pressure);
}

/// Get the pressure of the METAR.
MetarPressure get pressure => _pressure;

void _handleRecentWeather(String group) {
final match = MetarRegExp.RECENT_WEATHER.firstMatch(group);
_recentWeather = MetarRecentWeather(group, match);
Expand All @@ -125,8 +98,8 @@ class Metar extends Report
/// Get the recent weather data of the METAR.
MetarRecentWeather get recentWeather => _recentWeather;

void _handleWindshear(String group) {
final match = MetarRegExp.WINDSHEAR.firstMatch(group);
void _handleWindshearRunway(String group) {
final match = MetarRegExp.WINDSHEAR_RUNWAY.firstMatch(group);
final windshear = MetarWindshearRunway(group, match);
_windshear.add(windshear);

Expand Down Expand Up @@ -190,9 +163,9 @@ class Metar extends Report
GroupHandler(MetarRegExp.TEMPERATURES, _handleTemperatures),
GroupHandler(MetarRegExp.PRESSURE, _handlePressure),
GroupHandler(MetarRegExp.RECENT_WEATHER, _handleRecentWeather),
GroupHandler(MetarRegExp.WINDSHEAR, _handleWindshear),
GroupHandler(MetarRegExp.WINDSHEAR, _handleWindshear),
GroupHandler(MetarRegExp.WINDSHEAR, _handleWindshear),
GroupHandler(MetarRegExp.WINDSHEAR_RUNWAY, _handleWindshearRunway),
GroupHandler(MetarRegExp.WINDSHEAR_RUNWAY, _handleWindshearRunway),
GroupHandler(MetarRegExp.WINDSHEAR_RUNWAY, _handleWindshearRunway),
GroupHandler(MetarRegExp.SEA_STATE, _handleSeaState),
GroupHandler(MetarRegExp.RUNWAY_STATE, _handleRunwayState),
];
Expand Down Expand Up @@ -242,9 +215,9 @@ class Metar extends Report
space: 'left',
);

String trend = '';
String remark = '';
String body = '';
var trend = '';
var remark = '';
var body = '';
for (final section in sections) {
if (section.startsWith('TEMPO') ||
section.startsWith('BECMG') ||
Expand All @@ -262,3 +235,7 @@ class Metar extends Report
_sections.add(remark);
}
}

String sanitizeWindToken(String code) {
return code.replaceAll(' WND ', ' WND_');
}
13 changes: 13 additions & 0 deletions lib/src/models/metar/models/pressure.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,16 @@ class MetarPressure extends Pressure with GroupMixin {
}
}
}

mixin PressureMixin on StringAttributeMixin {
late MetarPressure _pressure = MetarPressure(null, null);

void _handlePressure(String group) {
final match = MetarRegExp.PRESSURE.firstMatch(group);
_pressure = MetarPressure(group, match);

_concatenateString(_pressure);
}

MetarPressure get pressure => _pressure;
}
1 change: 1 addition & 0 deletions lib/src/models/metar/models/time.dart
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ class MetarTime extends Time with GroupMixin {
}

mixin MetarTimeMixin on Report {
// ignore: prefer_final_fields
MetarTime _time = MetarTime(null, null);
}
7 changes: 6 additions & 1 deletion lib/src/models/metar/models/weather.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,12 @@ class MetarWeather extends Group {
if (match != null) {
_intensity = INTENSITY[match.namedGroup('int')];
_description = DESCRIPTION[match.namedGroup('desc')];
_precipitation = PRECIPITATION[match.namedGroup('prec')];
final prec = match.namedGroup('prec');
final prec2 = match.namedGroup('prec2');
if (prec != null || prec2 != null) {
_precipitation =
'${PRECIPITATION[prec]}${prec2 == null ? '' : ' ${PRECIPITATION[prec2]}'}';
}
_obscuration = OBSCURATION[match.namedGroup('obsc')];
_other = OTHER[match.namedGroup('other')];
}
Expand Down
9 changes: 8 additions & 1 deletion lib/src/models/metar/models/weather_trend.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@ class Forecast extends Group
MetarWindMixin,
MetarPrevailingMixin,
MetarWeatherMixin,
MetarCloudMixin {
MetarCloudMixin,
TafWindshearMixin,
TafTurbulenceMixin,
PressureMixin,
TafTemperatureMixin,
TafIcingMixin,
TafAmendmentsMixin,
MetarWindVariationMixin {
final _unparsedGroups = <String>[];
Forecast(String code) : super(code);

Expand Down
13 changes: 13 additions & 0 deletions lib/src/models/metar/models/wind_variation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,16 @@ class MetarWindVariation extends Group {
double? get toInGradians =>
_to.converted(conversionDouble: Conversions.DEGREES_TO_GRADIANS);
}

mixin MetarWindVariationMixin on StringAttributeMixin {
MetarWindVariation _windVariation = MetarWindVariation(null, null);
void _handleWindVariation(String group) {
final match = MetarRegExp.WIND_VARIATION.firstMatch(group);
_windVariation = MetarWindVariation(group, match);

_concatenateString(_windVariation);
}

/// Get the wind variation directions of the METAR.
MetarWindVariation get windVariation => _windVariation;
}
6 changes: 6 additions & 0 deletions lib/src/models/models.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
library models;

import 'package:intl/intl.dart';
import 'package:tuple/tuple.dart';

import '../utils/utils.dart';
Expand Down Expand Up @@ -46,4 +47,9 @@ part 'taf/models/change_indicator.dart';
part 'taf/models/missing.dart';
part 'taf/models/temperature.dart';
part 'taf/models/valid.dart';
part 'taf/models/windshear.dart';
part 'taf/models/turbulence.dart';
part 'taf/models/icing.dart';
part 'taf/models/amendments.dart';
part 'taf/models/automated_sensor_metwatch.dart';
part 'taf/taf.dart';
2 changes: 1 addition & 1 deletion lib/src/models/report.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ abstract class Report with StringAttributeMixin {
void _handleStation(String group) {
_station = Station(group, 'ICAO');

_concatenateString(_station);
// _concatenateString(_station);
}

/// Get the station data of the report.
Expand Down
78 changes: 78 additions & 0 deletions lib/src/models/taf/models/amendments.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
part of models;

/// Basic structure for valid time groups in change periods and forecasts.
class TafAmendments extends Group {
TafAmendments(String? code) : super(code);

DateTime? after, next;
bool nextNotSked = false;

/// Named constructor of the TafAmendments clas
///
/// Args:
/// code (String?): the code of the group.
/// match (RegExpMatch?): the match of the regular expression.
TafAmendments.fromTaf(String? code, RegExpMatch? match) : super(code) {
if (match != null) {
final afterd = match.namedGroup('afterd') ?? match.namedGroup('afterd2');
final afterh = match.namedGroup('afterh') ?? match.namedGroup('afterh2');
final nextd = match.namedGroup('nextd');
final nexth = match.namedGroup('nextd');

if (match.input == 'AMD_NOT_SKED' || (afterd == null && nexth == null)) {
nextNotSked = true;
return;
}

after = DateTime(
DateTime.now().year,
DateTime.now().month,
int.parse(afterd!),
int.parse(afterh!),
0,
);

if (nextd != null && nexth != null) {
next = DateTime(
DateTime.now().year,
DateTime.now().month,
int.parse(nextd),
int.parse(nexth),
0,
);
}
}
}

@override
String toString() {
if (nextNotSked) {
return 'AMD_NOT_SKED';
}
if (next != null) {
return 'No amendments between ${after!.hour}:00 UTC on the ${after!.day}${daySuffix(after!.day)} and ${next!.hour}:00 UTC on the ${next!.day}${daySuffix(next!.day)}';
}
return 'No amendments after ${after!.hour}:00 UTC on the ${after!.day}${daySuffix(after!.day)}';
}
}

/// Mixin to add the valid period of forecast attribute and handler.
mixin TafAmendmentsMixin on StringAttributeMixin {
late final TafAmendments _amendment;

void _handleAmendment(String group) {
final match = TafRegExp.AMENDMENTS.firstMatch(group);
_amendment = TafAmendments.fromTaf(group, match);
_concatenateString(_amendment);
}

TafAmendments get ammendment => _amendment;
}

String sanitizeAmendments(String code) {
return code
.replaceAll(' LAST NO AMDS AFT ', ' LAST_NO_AMDS_AFT_')
.replaceAll(' AFT ', ' AFT_')
.replaceAll(' NEXT ', '_NEXT_')
.replaceAll(' AMD NOT SKED', ' AMD_NOT_SKED');
}
24 changes: 24 additions & 0 deletions lib/src/models/taf/models/automated_sensor_metwatch.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
part of models;

/// Basic structure for missing TAF.
class AutomatedSensorMetwatch extends Modifier {
DateTime? from, to;

AutomatedSensorMetwatch(String? code, RegExpMatch match) : super(null) {
_code = code;

final fd = match.namedGroup('df')!;
final fh = match.namedGroup('hf')!;
final td = match.namedGroup('dt')!;
final th = match.namedGroup('ht')!;

final n = DateTime.now().toUtc();
from = DateTime(n.year, n.month, int.parse(fd), int.parse(fh), 0, 0);
to = DateTime(n.year, n.month, int.parse(td), int.parse(th), 0, 0);
}

@override
String toString() {
return 'Automated Sensor Metwatch from ${from!.hour}:00 UTC on the ${from!.day}${daySuffix(from!.day)} to ${to!.hour}:00 UTC on the ${to!.day}${daySuffix(to!.day)}';
}
}
27 changes: 26 additions & 1 deletion lib/src/models/taf/models/change_forecast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,47 @@ class ChangeForecast extends Forecast {
GroupHandler(MetarRegExp.WEATHER, _handleWeather),
GroupHandler(MetarRegExp.WEATHER, _handleWeather),
GroupHandler(MetarRegExp.WEATHER, _handleWeather),
GroupHandler(MetarRegExp.VISIBILITY, _handlePrevailing),
GroupHandler(MetarRegExp.CLOUD, _handleCloud),
GroupHandler(MetarRegExp.CLOUD, _handleCloud),
GroupHandler(MetarRegExp.CLOUD, _handleCloud),
GroupHandler(MetarRegExp.CLOUD, _handleCloud),
GroupHandler(TafRegExp.WINDSHEAR, _handleWindshear),
GroupHandler(TafRegExp.TURBULENCE, _handleTurbulence),
GroupHandler(TafRegExp.ICING, _handleIcing),
GroupHandler(TafRegExp.TURBULENCE, _handleTurbulence),
GroupHandler(TafRegExp.ICING, _handleIcing),
GroupHandler(TafRegExp.TURBULENCE, _handleTurbulence),
GroupHandler(TafRegExp.ICING, _handleIcing),
GroupHandler(MetarRegExp.PRESSURE, _handlePressure),
GroupHandler(MetarRegExp.PRESSURE, _handlePressure),
GroupHandler(TafRegExp.WIND, _handleWind),
GroupHandler(MetarRegExp.WIND_VARIATION, _handleWindVariation),
GroupHandler(TafRegExp.AMENDMENTS, _handleAmendment),
GroupHandler(TafRegExp.TEMPERATURE,
(e) => _handleTemperature(e, time: _valid.periodFrom.time)),
GroupHandler(TafRegExp.TEMPERATURE,
(e) => _handleTemperature(e, time: _valid.periodFrom.time)),
GroupHandler(TafRegExp.TEMPERATURE,
(e) => _handleTemperature(e, time: _valid.periodFrom.time)),
GroupHandler(TafRegExp.TEMPERATURE,
(e) => _handleTemperature(e, time: _valid.periodFrom.time)),
GroupHandler(TafRegExp.AMENDMENTS, _handleAmendment),
GroupHandler(TafRegExp.WINDSHEAR, _handleWindshear),
];

var sanitizedCode = sanitizeChangeIndicator(_code!);
sanitizedCode = sanitizeVisibility(sanitizedCode);
sanitizedCode = sanitizeWindToken(sanitizedCode);
sanitizedCode = sanitizeAmendments(sanitizedCode);
final unparsed = parseSection(handlers, sanitizedCode);
_unparsedGroups.addAll(unparsed);
}
}

/// Basic structure for weather change periods in TAF.
class TafChangePeriods extends GroupList<ChangeForecast> {
TafChangePeriods() : super(8);
TafChangePeriods() : super(20);

@override
String toString() {
Expand Down
Loading