def test_altimeter_in_weather_from_metar_str_no_altimeter_given(): wx = elib_wx.Weather( 'KLAW 121053Z AUTO 10SM -RA OVC050 13/12 RMK AO2 LTG DSNT W RAB0957E08B45 SLP159 P0001 T01330122' ) assert isinstance(wx, elib_wx.Weather) assert wx.altimeter.value() assert 720 <= wx.altimeter.value() <= 790
def test_generate_dcs_weather_rain_debug(): _min_coverage = 5 metar = f'KLAW 121053Z AUTO 06006KT 10SM +RA BKN050 M01/M01 Q1013' wx = elib_wx.Weather(metar) dcs_wx = wx.generate_dcs_weather() assert 1 == dcs_wx.precipitation_code assert 0 <= dcs_wx.temperature
def test_generate_dcs_weather(test_data): metar, expected = test_data wx = elib_wx.Weather(metar) dcs_wx = wx.generate_dcs_weather() for test_value in expected: expected, actual = test_value.verify(dcs_wx) assert expected == actual
def test_generate_dcs_weather_cloud_layers(coverage, range_): _min_coverage = 0 metar = f'KLAW 121053Z AUTO 06006KT 10SM {coverage}050 13/12 Q1013' wx = elib_wx.Weather(metar) dcs_wx = wx.generate_dcs_weather() assert max(_min_coverage, range_[0]) <= dcs_wx.cloud_density <= max( _min_coverage, range_[1])
def test_apply_to_miz_file_exists(test_data, wx_test_file_1): metar, _ = test_data wx = elib_wx.Weather(metar) test_miz_file = Path('./test.miz').absolute() test_miz_file.touch() with pytest.raises(elib_wx.FileAlreadyExistsError): wx.apply_to_miz(str(wx_test_file_1), str(test_miz_file))
def test_visibility_in_weather_from_metar_str_no_visibility_given(): wx = elib_wx.Weather( 'KLAW 121053Z AUTO -RA OVC050 13/12 RMK AO2 LTG DSNT W RAB0957E08B45 SLP159 P0001 T01330122' ) assert isinstance(wx, elib_wx.Weather) assert wx.visibility.value() assert 2000 <= wx.visibility.value() <= 20000
def test_generate_data_for_review(all_metar_strings, examples_data_file, with_db): elib_wx_logger = logging.getLogger('elib.wx') elib_wx_logger.propagate = True logger = logging.getLogger('') logger.setLevel(logging.INFO) handler = CustomHandler() logger.addHandler(handler) logger.addHandler(logging.StreamHandler()) counter = 1 for metar_str in all_metar_strings: try: logger.info('# example %s', counter) logger.info('## raw metar:\n%s', metar_str) wx = elib_wx.Weather(metar_str) logger.info( '## speech produced by third party library\n%s', elib_wx.avwx.speech.metar(wx.metar_data, wx.metar_units)) try: logger.info('## speech meant to be read:\n%s', wx.as_str()) logger.info( '## speech meant to be used in TTS engine to produce MP3 files:\n%s', wx.as_speech()) except IndexError: pytest.fail(metar_str) dcs_weather = wx.generate_dcs_weather() logger.info('## DCS weather:\n%s', dcs_weather.__repr__()) logger.info('-' * 300) counter += 1 except elib_wx.BadStationError: pass print('writing test result to:', examples_data_file) handler.process(examples_data_file)
def test_from_miz_caucasus(caucasus_test_file): wx = elib_wx.Weather(str(caucasus_test_file)) assert str(caucasus_test_file) == wx.source assert 'MIZ file' == wx.source_type assert 9999 == wx.visibility.value() assert 20 == wx.temperature.value() assert wx.dew_point.value() < wx.temperature.value() assert 'NOSIG' == wx.remarks assert 'XXXX' == wx.station_icao assert 'unknown airport (XXXX)' == wx.station_name assert [] == wx.cloud_layers assert '040000Z' == wx.date_time.repr assert 180 == wx.wind_direction.value() assert 0 == wx.wind_speed.value() assert 0 == wx.wind_gust.value() assert [] == wx.wind_direction_range assert wx.wind_direction_is_variable is False assert [] == wx.other assert f'XXXX 040000Z 18000KTS 9999M 20/{wx.dew_point.value():02d} Q1013 NOSIG' == wx.raw_metar_str assert 'Weather for unknown airport (XXXX) on Thursday the 01st of September at 0400 zulu. Wind calm. CAVOK. ' \ f'Temperature 20°C, 68°F. Dew point {wx.dew_point.value():02d}°C, {wx.dew_point.value(unit="f"):02d}°F. ' \ f'Altimeter 760mmHg, 1013hPa, 29.92inHg. ' \ 'No significant change.' == wx.as_str() dew_point_c = _CONVERT.number_to_words(wx.dew_point.value(), group=1).replace(',', '') dew_point_f = _CONVERT.number_to_words(wx.dew_point.value(unit='f'), group=1).replace(',', '') assert 'Weather for unknown airport (XXXX) on Thursday the first of September at zero four zero zero zulu. ' \ 'Wind calm. cavok. Temperature two zero degrees celsius, six eight degrees fahrenheit. ' \ f'Dew point {dew_point_c} degrees celsius, {dew_point_f} degrees fahrenheit. ' \ 'Altimeter seven six zero millimeters of mercury, ' \ 'one zero one three hecto Pascals, ' \ 'two nine point nine two inches of mercury. ' \ 'No significant change.' == wx.as_speech()
def test_weather_from_icao_unknown_icao(): icao = 'KLXX' expect(elib_wx.avwx.metar).fetch(icao).thenReturn('raw metar str') expect(elib_wx.avwx.metar).parse(icao, 'raw metar str').thenReturn( ('metar data', 'metar units')) expect(elib_wx.Weather).fill_from_metar_data() wx = elib_wx.Weather(icao) assert 'unknown airport (KLXX)' == wx.station_name
def test_turbulence_but_wind_speed_zero(): wx = elib_wx.Weather( 'KLAW 121053Z AUTO 06006G12KT 10SM OVC050 13/12 Q1013') wx.wind_speed._raw_value = 0 assert wx.wind_gust.value() > 0 dcs_wx = wx.generate_dcs_weather() assert dcs_wx.turbulence > 0 assert 1 == dcs_wx.wind_ground_speed assert 1 == wx.wind_speed.value()
def test_wind_in_weather_from_metar_str_no_wind_given(): wx = elib_wx.Weather( 'KLAW 121053Z AUTO 10SM -RA OVC050 13/12 A3001 RMK AO2 LTG DSNT W RAB0957E08B45 SLP159 P0001 T01330122' ) assert isinstance(wx, elib_wx.Weather) assert wx.wind_direction.value() assert 0 <= wx.wind_direction.value() <= 359 assert wx.wind_speed.value() assert 0 <= wx.wind_speed.value() <= 25
def test_apply_to_miz(test_data, wx_test_file_1): test_miz_file = './test.miz' metar, expected = test_data wx = elib_wx.Weather(metar) wx.apply_to_miz(str(wx_test_file_1), test_miz_file) with elib_miz.Miz(test_miz_file) as miz: for test_value in expected: expected, actual = test_value.verify(miz.mission.weather) assert expected == actual
def test_generate_dcs_weather_snow(coverage, range_, snow_marker, modifier, temperature): _min_coverage = 5 metar = f'KLAW 121053Z AUTO 06006KT 10SM {modifier}{snow_marker} {coverage}050 {temperature}/// Q1013' wx = elib_wx.Weather(metar) dcs_wx = wx.generate_dcs_weather() assert max(_min_coverage, range_[0]) <= dcs_wx.cloud_density <= max( _min_coverage, range_[1]) assert dcs_wx.temperature < 0 assert 3 == dcs_wx.precipitation_code
def test_all_metars(metar_string): if metar_string[0] not in ('O', 'K', 'U'): return assert isinstance(metar_string, str) try: wx = elib_wx.Weather(metar_string) assert isinstance(wx, elib_wx.Weather) wx.as_speech() except elib_wx.BadStationError: pass
def test_generate_dcs_weather_rain(coverage, range_, rain_marker, modifier, temperature): _min_coverage = 5 metar = f'KLAW 121053Z AUTO 06006KT 10SM {modifier}{rain_marker} {coverage}050 ///// Q1013' wx = elib_wx.Weather(metar) wx.temperature = Temperature(temperature) dcs_wx = wx.generate_dcs_weather() assert max(_min_coverage, range_[0]) <= dcs_wx.cloud_density <= max( _min_coverage, range_[1]) assert 1 == dcs_wx.precipitation_code assert 0 <= dcs_wx.temperature
def show(metar_or_icao: str): """ Displays the weather for an arbitrary given ICAO or METAR string """ _weather = elib_wx.Weather(metar_or_icao) message = f'Weather for: {metar_or_icao}\n\n' \ f'METAR:\n{_weather.raw_metar_str}\n\n' \ f'Weather:\n{_weather.as_str()}\n\n' \ f'DCS weather (warning: this is an example only, a different DCS weather will be generated each time):' \ f'\n{_weather.generate_dcs_weather()}' commands.DISCORD.say(message)
def test_weather_from_icao(with_db): icao = 'EBBR' expect(elib_wx.avwx.metar).fetch(icao).thenReturn('raw metar str') expect(elib_wx.avwx.metar).parse(icao, 'raw metar str').thenReturn( ('metar data', 'metar units')) expect(elib_wx.Weather).fill_from_metar_data() wx = elib_wx.Weather(icao) assert wx.source_type == 'ICAO' assert wx.metar_data == 'metar data' assert wx.metar_units == 'metar units' assert wx.station_name == 'Brussels Airport'
def test_generate_dcs_weather_dust(dust_marker, modifier, visibility): metar = f'KLAW 121053Z AUTO 06006KT {visibility:04d} {modifier}{dust_marker} 050 13/12 Q1013' wx = elib_wx.Weather(metar) dcs_wx = wx.generate_dcs_weather() dust_visibility = (min(300, visibility), max(3000, visibility)) if visibility <= 5000: assert dcs_wx.dust_enabled is True assert max(300, dust_visibility[0]) <= dcs_wx.dust_density <= min( 3000, dust_visibility[1]) else: assert dcs_wx.dust_enabled is False assert 3000 == dcs_wx.dust_density
def test(density, modifier, altitude): metar_str = f'KLAW 121053Z AUTO 06006KT 2SM -RA {density}{altitude:03d}{modifier} 13/12 A300' wx = elib_wx.Weather(metar_str) cloud_layer = wx.cloud_layers[0] assert cloud_layer.altitude == altitude if modifier == '': assert cloud_layer.modifier is None else: assert cloud_layer.modifier == modifier assert cloud_layer.repr == f'{density}{altitude:03d}{modifier}' cloud_str = wx._clouds_as_str(spoken=False) if modifier != '': assert elib_wx.static.CLOUD_TRANSLATIONS[modifier] in cloud_str
def initial_setup(): """ Runs at the start of the DCS loop, to initialize the first mission """ LOGGER.debug('initializing first mission') mission = get_running_mission() if isinstance(mission, MissionPath): LOGGER.info('building METAR for initial mission: %s', mission.orig_name) weather = elib_wx.Weather(str(mission.path)) core.Status.metar = weather esst.atis.create.generate_atis(weather) else: LOGGER.error('no initial mission found')
def test_from_miz_heavy_dust(wx_test_file_heavy_dust): wx = elib_wx.Weather(str(wx_test_file_heavy_dust)) assert str(wx_test_file_heavy_dust) == wx.source assert 'MIZ file' == wx.source_type assert 4710 == wx.visibility.value() assert 10 == wx.temperature.value() assert wx.dew_point.value() < wx.temperature.value() assert 'NOSIG' == wx.remarks assert 'XXXX' == wx.station_icao assert 'unknown airport (XXXX)' == wx.station_name assert [ elib_wx.avwx.structs.Cloud(repr='SCT016', type='SCT', altitude=16, modifier=None) ] == wx.cloud_layers assert '080000Z' == wx.date_time.repr assert 277 == wx.wind_direction.value() assert 5 == wx.wind_speed.value() assert 7 == wx.wind_gust.value() assert [] == wx.wind_direction_range assert wx.wind_direction_is_variable is False assert ['DS', 'RA'] == wx.other assert f'XXXX 080000Z 27710KTS 4710M DS RA SCT016 ' \ f'10/{wx.dew_point.value():02d} Q0987 NOSIG' == wx.raw_metar_str assert 'Weather for unknown airport (XXXX) on Wednesday the 01st of June at 0800 zulu. ' \ 'Wind 277 10kts (gusting 14kts knots). ' \ 'Visibility 4710m, 2.93SM. ' \ 'Temperature 10°C, 50°F. ' \ f'Dew point {wx.dew_point.value()}°C, {wx.dew_point.value(unit="f")}°F. ' \ 'Altimeter 740mmHg, 987hPa, 29.13inHg. ' \ 'Duststorm. ' \ 'Rain. ' \ 'Scattered clouds at 1600ft. ' \ 'No significant change.' == wx.as_str() dew_point_c = _CONVERT.number_to_words(wx.dew_point.value(), group=1).replace(',', '') dew_point_f = _CONVERT.number_to_words(wx.dew_point.value(unit='f'), group=1).replace(',', '') assert 'Weather for unknown airport (XXXX) on Wednesday the first of June at zero eight zero zero zulu. ' \ 'Wind two seven seven one zero knots (gusting one four knots knots). ' \ 'Visibility four thousand seven hundred and ten meters, two point nine three miles. ' \ 'Temperature one zero degrees celsius, five zero degrees fahrenheit. ' \ f'Dew point {dew_point_c} degrees celsius, {dew_point_f} degrees fahrenheit. ' \ 'Altimeter seven four zero millimeters of mercury, nine eight seven hecto Pascals, two nine point one ' \ 'three inches of mercury. ' \ 'Duststorm. ' \ 'Rain. ' \ 'Scattered clouds at one thousand six hundred feet. ' \ 'No significant change.' == wx.as_speech()
def test_from_miz_nevada(nevada_test_file): wx = elib_wx.Weather(str(nevada_test_file)) assert wx.source == str(nevada_test_file) assert 'MIZ file' == wx.source_type assert '150000Z' == wx.date_time.repr assert 'Weather for unknown airport (XXXX) on Wednesday the 01st of June at 1500 zulu. Wind calm. CAVOK. ' \ f'Temperature 20°C, 68°F. Dew point {wx.dew_point.value():02d}°C, {wx.dew_point.value(unit="f"):02d}°F. ' \ f'Altimeter 760mmHg, 1013hPa, 29.92inHg. ' \ 'No significant change.' == wx.as_str() dew_point_c = _CONVERT.number_to_words(wx.dew_point.value(), group=1).replace(',', '') dew_point_f = _CONVERT.number_to_words(wx.dew_point.value(unit='f'), group=1).replace(',', '') assert 'Weather for unknown airport (XXXX) on Wednesday the first of June at one five zero zero zulu. ' \ 'Wind calm. cavok. Temperature two zero degrees celsius, six eight degrees fahrenheit. ' \ f'Dew point {dew_point_c} degrees celsius, {dew_point_f} degrees fahrenheit. ' \ 'Altimeter seven six zero millimeters of mercury, ' \ 'one zero one three hecto Pascals, ' \ 'two nine point nine two inches of mercury. ' \ 'No significant change.' == wx.as_speech()
def set_as_active(self, weather: elib_wx.Weather = None): """ Write the settings file to set this mission as active :param weather: current weather; if not provided, will be inferred from MIZ file :type weather: elib_wx.Weather """ LOGGER.info('setting active mission to: %s', self.name) if not self: LOGGER.error('mission file not found: %s', self.path) return write_server_settings(str(self.path).replace('\\', '/')) if weather is None: LOGGER.debug('building metar from mission: %s', self.name) # noinspection SpellCheckingInspection weather = elib_wx.Weather(str(self.path)) LOGGER.info('metar for %s:\n%s', self.name, weather) else: esst.atis.create.generate_atis(weather) core.Status.metar = weather
def test_weather_from_icao_wrong_icao(): icao = '1234' with pytest.raises(elib_wx.BadStationError): elib_wx.Weather(icao)
def _load(name, metar_or_icao, time, max_wind, min_wind, force): # noqa: C901 if max_wind or min_wind: LOGGER.warning( '"min_wind" and "max_wind" have been disabled for the time being') if name is None: mission = missions_manager.get_running_mission() if not mission: LOGGER.error('unable to retrieve current mission') return else: try: LOGGER.debug('trying to cast mission name into an int: %s', name) mission_number = int(name) except ValueError: LOGGER.debug('loading mission name: %s', name) mission = missions_manager.MissionPath(name) if not mission: LOGGER.debug('mission path not found: %s', mission.path) LOGGER.error('mission file not found: %s', mission.name) return else: LOGGER.debug('loading mission number: %s', mission_number) mission = _mission_index_to_mission_name(mission_number) if not mission: LOGGER.error( 'invalid mission index: %s; use "!mission show" to see available indices', mission_number) return LOGGER.info('loading mission file: %s', mission.path) if time: try: mission_time = elib_miz.MissionTime.from_string(time) LOGGER.info('setting mission time: %s', mission_time.iso_format) except elib_miz.exc.InvalidDateTimeString: LOGGER.error('invalid date-time string: %s', time) return except ValueError as err: LOGGER.error(err) return else: mission_time = None if metar_or_icao: LOGGER.info('analyzing METAR string: %s', metar_or_icao) try: weather_ = elib_wx.Weather(metar_or_icao) LOGGER.info('setting mission weather: %s', weather_.as_str()) except elib_wx.BadStationError: LOGGER.error('wrong ICAO code: %s', metar_or_icao) return LOGGER.info('METAR: %s', weather_.raw_metar_str) else: LOGGER.info('building METAR from mission file') # noinspection SpellCheckingInspection weather_ = elib_wx.Weather(str(mission.path)) LOGGER.info('METAR: %s', weather_.as_str()) commands.DCS.block_start('loading mission') commands.DCS.kill(force=force) try: LOGGER.debug('waiting on DCS application to close') while core.Status.dcs_application != 'not running': sleep(1) LOGGER.debug('DCS has closed, carrying on') active_mission = mission if time: mission_time.apply_to_miz(str(mission.path), str(mission.auto.path), overwrite=True) active_mission = mission.auto if metar_or_icao: weather_.apply_to_miz(str(mission.path), str(mission.auto.path), overwrite=True) active_mission = mission.auto active_mission.set_as_active(weather_) finally: commands.DCS.unblock_start('loading mission')
def test_altimeter_in_weather_from_metar_str(metar_str, expected): wx = elib_wx.Weather(metar_str) assert isinstance(wx, elib_wx.Weather) for test_value in expected: expected, actual = test_value.verify(wx) assert expected == actual
def test_unknown_modifier(): metar_str = 'KLAW 121053Z AUTO 06006KT 2SM -RA BKN150XXX 13/12 A3001' wx = elib_wx.Weather(metar_str) assert 'Broken layer at 15000ft.' == wx._clouds_as_str(spoken=False)
def test_no_altitude(): metar_str = 'KLAW 121053Z AUTO 06006KT 2SM -RA BKN150 13/12 A3001' wx = elib_wx.Weather(metar_str) wx.cloud_layers[0].altitude = None assert 'Sky clear.' == wx._clouds_as_str(spoken=False)
def test_temperature_in_weather_from_metar_str_no_temperature_given(): wx = elib_wx.Weather( 'KLAW 121053Z AUTO 10SM -RA OVC050 RMK AO2 LTG DSNT W RAB0957E08B45 SLP159 P0001 T01330122' ) assert isinstance(wx, elib_wx.Weather) assert wx.dew_point.value() < wx.temperature.value()
def _parse_metar_string(metar_str: str) -> typing.Optional[elib_wx.Weather]: LOGGER.debug('parsing METAR string') # noinspection SpellCheckingInspection return elib_wx.Weather(metar_str)