def _make_precipitations(weather_object, mission_weather):
    if mission_weather.precipitation_code == 1:
        LOGGER.debug('rain found in mission')
        weather_object.other.append('RA')
    if mission_weather.precipitation_code == 2:
        LOGGER.debug('thunderstorm found in mission')
        weather_object.other.append('+RATS')
    if mission_weather.precipitation_code == 3:
        LOGGER.debug('snow found in mission')
        weather_object.other.append('SN')
    if mission_weather.precipitation_code == 4:
        LOGGER.debug('blizzard found in mission')
        weather_object.other.append('+BLSN')
Beispiel #2
0
def _make_clouds(weather_object) -> typing.Tuple[int, int, int]:
    cloud_density = 0
    cloud_base = 300
    cloud_thickness = 200
    _layer_in_use = None
    for _layer in weather_object.cloud_layers:
        _coverage = random.randint(*CLOUD_METAR_TO_DCS[_layer.type])  # nosec
        if _coverage > cloud_density:
            cloud_density = _coverage
            _layer_in_use = _layer
    if _layer_in_use:
        LOGGER.debug('using cloud layer: %s', _layer_in_use.repr)
        if not _layer_in_use.altitude:
            LOGGER.warning(
                'no cloud altitude data found in METAR, using random number between 5 and 35 thousand feet'
            )
            cloud_base = random.randint(5, 25) * 1000  # nosec
        else:
            if not weather_object.metar_units.altitude == 'ft':
                raise ValueError(weather_object.metar_units.altitude)
            cloud_base = CloudBase(_layer_in_use.altitude * 100, 'ft').value('m')
        cloud_thickness = int(cloud_density / 10 * 2000)
    else:
        LOGGER.debug('no clouds')

    cloud_base = DCSWeather.normalize_cloud_base(cloud_base)
    cloud_thickness = DCSWeather.normalize_cloud_thickness(cloud_thickness)

    return cloud_base, cloud_density, cloud_thickness
Beispiel #3
0
def _parse_cloud_layer_as_str(self, cloud, ret: list, spoken: bool):
    if cloud.altitude is None:
        LOGGER.warning('no altitude given, skipping cloud layer: %s',
                       cloud.repr)
        return
    cloud_str = static.CLOUD_TRANSLATIONS[cloud.type]
    if cloud.modifier:
        try:
            cloud_str += f' ({static.CLOUD_TRANSLATIONS[cloud.modifier]})'
        except KeyError:
            LOGGER.warning('unknown cloud modifier: %s', cloud.modifier)
    altitude_as_str = str(cloud.altitude)
    while len(altitude_as_str) != 3:
        altitude_as_str = '0' + altitude_as_str
    if spoken:
        cloud_alt = []

        _cloud_alt_in_thousand_feet_str = int(cloud.altitude / 10)

        if _cloud_alt_in_thousand_feet_str > 0:
            cloud_alt.append(
                utils.num_to_words(_cloud_alt_in_thousand_feet_str, group=0) +
                ' thousand')

        clouds_altitude_hundreds = altitude_as_str[2]
        if clouds_altitude_hundreds != '0':
            cloud_alt.append(
                utils.num_to_words(clouds_altitude_hundreds, group=0))
            cloud_alt.append('hundred')

        cloud_alt.append('feet')
        ret.append(cloud_str.format(' '.join(cloud_alt)))
    else:
        cloud_base = Altitude(cloud.altitude * 100, self.metar_units.altitude)
        ret.append(
            cloud_str.format(cloud_base.to_string(unit='ft', spoken=spoken)))
def _make_date_time(weather_object, mission):
    LOGGER.debug('mission theatre is: %s', mission.theatre)
    if mission.theatre in (
            elib_miz.static.Theater.caucasus,
            elib_miz.static.Theater.persian_gulf,
    ):
        tz_info = datetime.timezone(offset=datetime.timedelta(hours=4))
    elif mission.theatre == elib_miz.static.Theater.nevada:
        tz_info = datetime.timezone(offset=-datetime.timedelta(hours=7))
    else:
        raise ValueError(f'Theatre not managed: {mission.theatre}')
    LOGGER.debug('using offset: %s', tz_info)
    date_time = datetime.datetime(year=mission.year,
                                  month=mission.month,
                                  day=mission.day,
                                  hour=mission.hour,
                                  minute=mission.minute,
                                  second=mission.second,
                                  tzinfo=tz_info)
    utc_time = date_time.astimezone(datetime.timezone.utc)
    weather_object.date_time = avwx.structs.Timestamp(
        repr=utc_time.strftime('%H%M%SZ'),
        dt=utc_time,
    )
Beispiel #5
0
def _make_precipitations(weather_object, temperature, cloud_density) -> typing.Tuple[int, int, int]:
    precipitation_code = 0
    for phenomenon in WEATHER_PHENOMENONS:
        for indicator in phenomenon.indicators:
            if any(indicator in other for other in weather_object.metar_data.other):
                precipitation_code = phenomenon.precipitation_code
                LOGGER.warning('%s reported in the area', phenomenon.name)
                if phenomenon.min_temp is not None and temperature < phenomenon.min_temp:
                    LOGGER.warning('forcing temperature to %s due to %s', phenomenon.min_temp, phenomenon.name)
                    temperature = phenomenon.min_temp
                if phenomenon.max_temp is not None and temperature > phenomenon.max_temp:
                    LOGGER.warning('forcing temperature to %s due to %s', phenomenon.max_temp, phenomenon.name)
                    temperature = phenomenon.max_temp
                if cloud_density < phenomenon.min_cloud_density:
                    LOGGER.warning('forcing cloud density to %s due to %s',
                                   phenomenon.min_cloud_density, phenomenon.name)
                    cloud_density = phenomenon.min_cloud_density
                break

    return precipitation_code, temperature, cloud_density
Beispiel #6
0
def weather_from_metar_string(weather_object: WeatherABC):
    """
    Creates a Weather object from a METAR string

    :param weather_object: weather object to fill
    :type weather_object: WeatherABC
    """
    LOGGER.debug('building Weather from METAR string')
    weather_object.source_type = 'METAR'
    LOGGER.debug('extracting station from METAR')
    weather_object.station_icao = utils.extract_station_from_metar_str(
        weather_object.source)
    LOGGER.debug('station: %s', weather_object.station_icao)
    weather_object.raw_metar_str = weather_object.source
    weather_object.metar_data, weather_object.metar_units = avwx.metar.parse(
        weather_object.station_icao, weather_object.raw_metar_str)
    weather_object.fill_from_metar_data()
def weather_from_metar_data(weather_object: WeatherABC):
    """
    Builds a Weather object from METAR data as parsed by AVWX

    :param weather_object: weather object to build
    :type weather_object: WeatherABC
    """
    LOGGER.debug('creating weather object based on METAR data')
    LOGGER.debug('METAR data: %s', weather_object.metar_data)
    LOGGER.debug('METAR units: %s', weather_object.metar_units)

    _make_altimeter(weather_object)
    _make_visibility(weather_object)
    weather_object.cloud_layers = [
        cloud_layer for cloud_layer in weather_object.metar_data.clouds
    ]
    _make_temperature(weather_object)
    _make_dew_point(weather_object)
    _make_wind(weather_object)

    weather_object.date_time = weather_object.metar_data.time
    weather_object.other = weather_object.metar_data.other
    weather_object.remarks = weather_object.metar_data.remarks
    LOGGER.debug('resulting weather object: %s', repr(weather_object))  # pylint: disable=possibly-unused-variable
Beispiel #8
0
def apply_weather_to_mission_dict(weather_object: WeatherABC, mission: elib_miz.Mission) -> elib_miz.Mission:
    """
    Generates a DCSWeather object from self and creates a new elib_miz.Mission object out of it

    :param weather_object: weather object to apply to mission dictionary
    :type weather_object: WeatherABC
    :param mission: mission to modify
    :type mission: elib_miz.Mission
    :return: new, modified mission
    :rtype: elib_miz.Mission
    """
    LOGGER.info('generating DCS weather')
    dcs_weather = weather_object.generate_dcs_weather()
    new_mission_dict = copy.deepcopy(mission.d)
    new_mission_l10n = copy.deepcopy(mission.l10n)
    new_mission = elib_miz.Mission(new_mission_dict, new_mission_l10n)
    LOGGER.debug('DCS weather: %s', pprint.pformat(dcs_weather))
    LOGGER.debug('applying weather to mission file')
    wxd = new_mission.weather
    wxd.altimeter = dcs_weather.altimeter
    wxd.turbulence = dcs_weather.turbulence
    wxd.temperature = dcs_weather.temperature
    wxd.wind_ground_speed = dcs_weather.wind_ground_speed
    wxd.wind_ground_dir = dcs_weather.wind_ground_dir
    wxd.wind_at2000_speed = dcs_weather.wind_2000_speed
    wxd.wind_at2000_dir = dcs_weather.wind_2000_dir
    wxd.wind_at8000_speed = dcs_weather.wind_8000_speed
    wxd.wind_at8000_dir = dcs_weather.wind_8000_dir
    wxd.precipitation_code = dcs_weather.precipitation_code
    wxd.cloud_base = dcs_weather.cloud_base
    wxd.cloud_density = dcs_weather.cloud_density
    wxd.cloud_thickness = dcs_weather.cloud_thickness
    wxd.fog_enabled = dcs_weather.fog_enabled
    wxd.fog_thickness = dcs_weather.fog_thickness
    wxd.fog_visibility = dcs_weather.fog_visibility
    wxd.dust_enabled = dcs_weather.dust_enabled
    wxd.dust_density = dcs_weather.dust_density
    return new_mission
def _make_clouds(
    weather_object,
    mission_weather,
):
    if mission_weather.cloud_density == 0:
        LOGGER.debug('no cloud found in mission')
        weather_object.cloud_layers = []
    else:
        LOGGER.debug('cloud density in mission: %s',
                     mission_weather.cloud_density)
        cloud_type = static.CLOUD_DCS_TO_METAR[mission_weather.cloud_density]
        LOGGER.debug('inferred cloud type: %s', cloud_type)
        LOGGER.debug('cloud base in mission: %s', mission_weather.cloud_base)
        cloud_alt = int(
            round(
                Altitude(mission_weather.cloud_base, 'm').value('ft') / 100,
                0))
        LOGGER.debug('inferred cloud altitude: %s', cloud_alt)
        weather_object.cloud_layers = [
            avwx.structs.Cloud(
                repr=f'{cloud_type}{cloud_alt:03d}',
                type=cloud_type,
                altitude=cloud_alt,
                modifier=None,
            )
        ]
        LOGGER.debug('resulting cloud layer: %s', weather_object.cloud_layers)
def weather_from_miz_file(weather_object: WeatherABC):
    """
    Creates a Weather object from a MIZ file

    :param weather_object: weather object to fill
    :type weather_object: WeatherABC
    """
    LOGGER.debug('building Weather from MIZ file')
    LOGGER.debug('source MIZ file: %s', weather_object.source)
    weather_object.station_icao = Config.dummy_icao_code
    weather_object.source_type = 'MIZ file'
    with elib_miz.Miz(weather_object.source) as miz:
        mission_weather = miz.mission.weather
        mission = miz.mission
    weather_object.altimeter = Pressure(mission_weather.altimeter, 'mmhg')
    LOGGER.debug('altimeter: %s', weather_object.altimeter)

    _make_clouds(weather_object, mission_weather)
    _make_fog(weather_object, mission_weather)

    LOGGER.debug('inferred visibility: %s', weather_object.visibility)
    weather_object.temperature = Temperature(mission_weather.temperature, 'c')
    LOGGER.debug('inferred temperature: %s', weather_object.temperature)
    weather_object.dew_point = weather_object.temperature.make_dummy_dew_point(
    )
    LOGGER.debug('inferred dew point: %s', weather_object.dew_point)

    _make_turbulence(weather_object, mission_weather)

    LOGGER.debug('inferred wind speed: %s', weather_object.wind_speed)
    LOGGER.debug('inferred wind gust: %s', weather_object.wind_gust)

    weather_object.wind_direction = WindDirection(
        mission_weather.wind_ground_dir).reverse()
    weather_object.wind_direction_is_variable = False
    weather_object.wind_direction_range = []

    _make_date_time(weather_object, mission)

    weather_object.other = []

    _make_dust(weather_object, mission_weather)

    _make_precipitations(weather_object, mission_weather)

    if weather_object.temperature.value() < 0:
        LOGGER.debug('freezing conditions found in mission')
        weather_object.other.append('FZ')
    LOGGER.debug('inferred others: %s', weather_object.other)
    weather_object.remarks = 'NOSIG'

    _make_metar(weather_object)

    # Store the original DCS weather so there's no discrepancies if we create a new one from this Weather
    dcs_wx = DCSWeather(altimeter=mission_weather.altimeter,
                        turbulence=mission_weather.turbulence,
                        temperature=mission_weather.temperature,
                        wind_ground_speed=mission_weather.wind_ground_speed,
                        wind_ground_dir=mission_weather.wind_ground_dir,
                        wind_2000_speed=mission_weather.wind_at2000_speed,
                        wind_2000_dir=mission_weather.wind_at2000_dir,
                        wind_8000_speed=mission_weather.wind_at8000_speed,
                        wind_8000_dir=mission_weather.wind_at8000_dir,
                        precipitation_code=mission_weather.precipitation_code,
                        cloud_density=mission_weather.cloud_density,
                        cloud_base=mission_weather.cloud_base,
                        cloud_thickness=mission_weather.cloud_thickness,
                        fog_enabled=mission_weather.fog_enabled,
                        fog_visibility=mission_weather.fog_visibility,
                        fog_thickness=mission_weather.fog_thickness,
                        dust_enabled=mission_weather.dust_enabled,
                        dust_density=mission_weather.dust_density)
    weather_object.original_dcs_weather = dcs_wx