diff options
Diffstat (limited to 'my-evolution/metar.c')
-rw-r--r-- | my-evolution/metar.c | 590 |
1 files changed, 590 insertions, 0 deletions
diff --git a/my-evolution/metar.c b/my-evolution/metar.c new file mode 100644 index 0000000000..353593da79 --- /dev/null +++ b/my-evolution/metar.c @@ -0,0 +1,590 @@ +/* + * metar.c: Metar decoding routines. + * + * Originally written by Papadimitriou Spiros <spapadim+@cs.cmu.ed> + */ + +#include <glib.h> + +#include <unistd.h> +#include <stdlib.h> +#include <regex.h> +#include <math.h> + +#include <libgnome/gnome-defs.h> +#include <libgnome/gnome-i18n.h> + +#include "e-summary.h" +#include "weather.h" + +#include "metar.h" + +static regex_t metar_re[RE_NUM]; + +/* Unit conversions and names */ + +#define TEMP_F_TO_C(f) (((f) - 32.0) * 0.555556) +#define TEMP_C_TO_F(c) (((c) * 1.8) + 32.0) +#define TEMP_UNIT_STR(units) (((units) == UNITS_IMPERIAL) ? "\260F" : "\260C") + +#define WINDSPEED_KNOTS_TO_KPH(knots) ((knots) * 1.851965) +#define WINDSPEED_KPH_TO_KNOTS(kph) ((kph) * 0.539967) +#define WINDSPEED_UNIT_STR(units) (((units) == UNITS_IMPERIAL) ? "knots" : "kph") + +#define PRESSURE_INCH_TO_MM(inch) ((inch) * 25.4) +#define PRESSURE_MM_TO_INCH(mm) ((mm) * 0.03937) +#define PRESSURE_MBAR_TO_INCH(mbar) ((mbar) * 0.02963742) +#define PRESSURE_UNIT_STR(units) (((units) == UNITS_IMPERIAL) ? "inHg" : "mmHg") +#define VISIBILITY_SM_TO_KM(sm) ((sm) * 1.609344) +#define VISIBILITY_KM_TO_SM(km) ((km) * 0.621371) +#define VISIBILITY_UNIT_STR(units) (((units) == UNITS_IMPERIAL) ? "miles" : "kilometers") + +static const char *sky_str[] = { + N_("Clear sky"), + N_("Broken clouds"), + N_("Scattered clouds"), + N_("Few clouds"), + N_("Overcast") +}; + +const char * +weather_sky_string (Weather *w) +{ + if (w->sky < 0 || + w->sky >= (sizeof (sky_str) / sizeof (char *))) { + return _("Invalid"); + } + + return _(sky_str[(int)w->sky]); +} + +static const char *wind_direction_str[] = { + N_("Variable"), + N_("North"), N_("North - NorthEast"), N_("Northeast"), N_("East - NorthEast"), + N_("East"), N_("East - Southeast"), N_("Southeast"), N_("South - Southeast"), + N_("South"), N_("South - Southwest"), N_("Southwest"), N_("West - Southwest"), + N_("West"), N_("West - Northwest"), N_("Northwest"), N_("North - Northwest")}; + +const char * +weather_wind_direction_string (Weather *w) +{ + if (w->wind < 0 || + w->wind >= (sizeof (wind_direction_str) / sizeof (char *))) { + return _("Invalid"); + } + + return _(wind_direction_str[(int)w->wind]); +} + +/* + * Even though tedious, I switched to a 2D array for weather condition + * strings, in order to facilitate internationalization, esp. for languages + * with genders. + * + * I tried to come up with logical names for most phenomena, but I'm no + * meteorologist, so there will undoubtedly be some stupid mistakes. + * However, combinations that did not seem plausible (eg. I cannot imagine + * what a "light tornado" may be like ;-) were filled in with "??". If this + * ever comes up in the weather conditions field, let me know... + */ + +/* + * Note, magic numbers, when you change the size here, make sure to change + * the below function so that new values are recognized + */ +static const gchar *conditions_str[24][13] = { +/* NONE VICINITY LIGHT MODERATE HEAVY SHALLOW PATCHES PARTIAL THUNDERSTORM BLOWING SHOWERS DRIFTING FREEZING */ +/* *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/ +/* NONE */ {"", "", "", "", "", "", "", "", "", "", "", "", "", }, +/* DRIZZLE */ {N_("Drizzle"), N_("Drizzle in the vicinity"), N_("Light drizzle"), N_("Moderate drizzle"), N_("Heavy drizzle"), N_("Shallow drizzle"), N_("Patches of drizzle"), N_("Partial drizzle"), N_("Thunderstorm"), N_("Windy drizzle"), N_("Showers"), N_("Drifting drizzle"), N_("Freezing drizzle") }, +/* RAIN */ {N_("Rain"), N_("Rain in the vicinity") , N_("Light rain"), N_("Moderate rain"), N_("Heavy rain"), N_("Shallow rain"), N_("Patches of rain"), N_("Partial rainfall"), N_("Thunderstorm"), N_("Blowing rainfall"), N_("Rain showers"), N_("Drifting rain"), N_("Freezing rain") }, +/* SNOW */ {N_("Snow"), N_("Snow in the vicinity") , N_("Light snow"), N_("Moderate snow"), N_("Heavy snow"), N_("Shallow snow"), N_("Patches of snow"), N_("Partial snowfall"), N_("Snowstorm"), N_("Blowing snowfall"), N_("Snow showers"), N_("Drifting snow"), N_("Freezing snow") }, +/* SNOW_GRAINS */ {N_("Snow grains"), N_("Snow grains in the vicinity") , N_("Light snow grains"), N_("Moderate snow grains"), N_("Heavy snow grains"), N_("Shallow snow grains"), N_("Patches of snow grains"), N_("Partial snow grains"), N_("Snowstorm"), N_("Blowing snow grains"), N_("Snow grain showers"), N_("Drifting snow grains"), N_("Freezing snow grains") }, +/* ICE_CRYSTALS */ {N_("Ice crystals"), N_("Ice crystals in the vicinity") , N_("Few ice crystals"), N_("Moderate ice crystals"), N_("Heavy ice crystals"), "??", N_("Patches of ice crystals"), N_("Partial ice crystals"), N_("Ice crystal storm"), N_("Blowing ice crystals"), N_("Showers of ice crystals"), N_("Drifting ice crystals"), N_("Freezing ice crystals") }, +/* ICE_PELLETS */ {N_("Ice pellets"), N_("Ice pellets in the vicinity") , N_("Few ice pellets"), N_("Moderate ice pellets"), N_("Heavy ice pellets"), N_("Shallow ice pellets"), N_("Patches of ice pellets"), N_("Partial ice pellets"), N_("Ice pellet storm"), N_("Blowing ice pellets"), N_("Showers of ice pellets"), N_("Drifting ice pellets"), N_("Freezing ice pellets") }, +/* HAIL */ {N_("Hail"), N_("Hail in the vicinity") , N_("Light hail"), N_("Moderate hail"), N_("Heavy hail"), N_("Shallow hail"), N_("Patches of hail"), N_("Partial hail"), N_("Hailstorm"), N_("Blowing hail"), N_("Hail showers"), N_("Drifting hail"), N_("Freezing hail") }, +/* SMALL_HAIL */ {N_("Small hail"), N_("Small hail in the vicinity") , N_("Light hail"), N_("Moderate small hail"), N_("Heavy small hail"), N_("Shallow small hail"), N_("Patches of small hail"), N_("Partial small hail"), N_("Small hailstorm"), N_("Blowing small hail"), N_("Showers of small hail"), N_("Drifting small hail"), N_("Freezing small hail") }, +/* PRECIPITATION */ {N_("Unknown precipitation"), N_("Precipitation in the vicinity"), N_("Light precipitation"), N_("Moderate precipitation"), N_("Heavy precipitation"), N_("Shallow precipitation"), N_("Patches of precipitation"), N_("Partial precipitation"), N_("Unknown thunderstorm"), N_("Blowing precipitation"), N_("Showers, type unknown"), N_("Drifting precipitation"), N_("Freezing precipitation") }, +/* MIST */ {N_("Mist"), N_("Mist in the vicinity") , N_("Light mist"), N_("Moderate mist"), N_("Thick mist"), N_("Shallow mist"), N_("Patches of mist"), N_("Partial mist"), "??", N_("Mist with wind"), "??", N_("Drifting mist"), N_("Freezing mist") }, +/* FOG */ {N_("Fog"), N_("Fog in the vicinity") , N_("Light fog"), N_("Moderate fog"), N_("Thick fog"), N_("Shallow fog"), N_("Patches of fog"), N_("Partial fog"), "??", N_("Fog with wind"), "??", N_("Drifting fog"), N_("Freezing fog") }, +/* SMOKE */ {N_("Smoke"), N_("Smoke in the vicinity") , N_("Thin smoke"), N_("Moderate smoke"), N_("Thick smoke"), N_("Shallow smoke"), N_("Patches of smoke"), N_("Partial smoke"), N_("Smoke w/ thunders"), N_("Smoke with wind"), "??", N_("Drifting smoke"), "??" }, +/* VOLCANIC_ASH */ {N_("Volcanic ash"), N_("Volcanic ash in the vicinity") , "??", N_("Moderate volcanic ash"), N_("Thick volcanic ash"), N_("Shallow volcanic ash"), N_("Patches of volcanic ash"), N_("Partial volcanic ash"), N_("Volcanic ash w/ thunders"), N_("Blowing volcanic ash"), N_("Showers of volcanic ash "), N_("Drifting volcanic ash"), N_("Freezing volcanic ash") }, +/* SAND */ {N_("Sand"), N_("Sand in the vicinity") , N_("Light sand"), N_("Moderate sand"), N_("Heavy sand"), "??", N_("Patches of sand"), N_("Partial sand"), "??", N_("Blowing sand"), "", N_("Drifting sand"), "??" }, +/* HAZE */ {N_("Haze"), N_("Haze in the vicinity") , N_("Light haze"), N_("Moderate haze"), N_("Thick haze"), N_("Shallow haze"), N_("Patches of haze"), N_("Partial haze"), "??", N_("Haze with wind"), "??", N_("Drifting haze"), N_("Freezing haze") }, +/* SPRAY */ {N_("Sprays"), N_("Sprays in the vicinity") , N_("Light sprays"), N_("Moderate sprays"), N_("Heavy sprays"), N_("Shallow sprays"), N_("Patches of sprays"), N_("Partial sprays"), "??", N_("Blowing sprays"), "??", N_("Drifting sprays"), N_("Freezing sprays") }, +/* DUST */ {N_("Dust"), N_("Dust in the vicinity") , N_("Light dust"), N_("Moderate dust"), N_("Heavy dust"), "??", N_("Patches of dust"), N_("Partial dust"), "??", N_("Blowing dust"), "??", N_("Drifting dust"), "??" }, +/* SQUALL */ {N_("Squall"), N_("Squall in the vicinity") , N_("Light squall"), N_("Moderate squall"), N_("Heavy squall"), "??", "??", N_("Partial squall"), N_("Thunderous squall"), N_("Blowing squall"), "??", N_("Drifting squall"), N_("Freezing squall") }, +/* SANDSTORM */ {N_("Sandstorm"), N_("Sandstorm in the vicinity") , N_("Light standstorm"), N_("Moderate sandstorm"), N_("Heavy sandstorm"), N_("Shallow sandstorm"), "??", N_("Partial sandstorm"), N_("Thunderous sandstorm"), N_("Blowing sandstorm"), "??", N_("Drifting sandstorm"), N_("Freezing sandstorm") }, +/* DUSTSTORM */ {N_("Duststorm"), N_("Duststorm in the vicinity") , N_("Light duststorm"), N_("Moderate duststorm"), N_("Heavy duststorm"), N_("Shallow duststorm"), "??", N_("Partial duststorm"), N_("Thunderous duststorm"), N_("Blowing duststorm"), "??", N_("Drifting duststorm"), N_("Freezing duststorm") }, +/* FUNNEL_CLOUD */ {N_("Funnel cloud"), N_("Funnel cloud in the vicinity") , N_("Light funnel cloud"), N_("Moderate funnel cloud"), N_("Thick funnel cloud"), N_("Shallow funnel cloud"), N_("Patches of funnel clouds"), N_("Partial funnel clouds"), "??", N_("Funnel cloud w/ wind"), "??", N_("Drifting funnel cloud"), "??" }, +/* TORNADO */ {N_("Tornado"), N_("Tornado in the vicinity") , "??", N_("Moderate tornado"), N_("Raging tornado"), "??", "??", N_("Partial tornado"), N_("Thunderous tornado"), N_("Tornado"), "??", N_("Drifting tornado"), N_("Freezing tornado") }, +/* DUST_WHIRLS */ {N_("Dust whirls"), N_("Dust whirls in the vicinity") , N_("Light dust whirls"), N_("Moderate dust whirls"), N_("Heavy dust whirls"), N_("Shallow dust whirls"), N_("Patches of dust whirls"), N_("Partial dust whirls"), "??", N_("Blowing dust whirls"), "??", N_("Drifting dust whirls"), "??" } +}; + +const char * +weather_conditions_string (Weather *w) +{ + if (!w->cond.significant) { + return "-"; + } else { + if (w->cond.phenomenon >= 0 && + w->cond.phenomenon < 24 && + w->cond.qualifier >= 0 && + w->cond.qualifier < 13) { + return _(conditions_str[(int)w->cond.phenomenon][(int)w->cond.qualifier]); + } else { + return _("Invalid"); + } + } +} + +char * +weather_temp_string (Weather *w) +{ + char *temp; + + temp = g_strdup_printf ("%.1f%s", w->temp, TEMP_UNIT_STR (w->units)); + return temp; +} + +void +metar_init_re (void) +{ + static gboolean initialized = FALSE; + if (initialized) + return; + initialized = TRUE; + + regcomp(&metar_re[TIME_RE], TIME_RE_STR, REG_EXTENDED); + regcomp(&metar_re[WIND_RE], WIND_RE_STR, REG_EXTENDED); + regcomp(&metar_re[VIS_RE], VIS_RE_STR, REG_EXTENDED); + regcomp(&metar_re[CLOUD_RE], CLOUD_RE_STR, REG_EXTENDED); + regcomp(&metar_re[TEMP_RE], TEMP_RE_STR, REG_EXTENDED); + regcomp(&metar_re[PRES_RE], PRES_RE_STR, REG_EXTENDED); + regcomp(&metar_re[COND_RE], COND_RE_STR, REG_EXTENDED); +} + +static inline gint +days_in_month (gint month, + gint year) +{ + if (month == 1) + return ((year % 4) == 0) ? 29 : 28; + else if (((month <= 6) && (month % 2 == 0)) || ((month >=7) && (month % 2 != 0))) + return 31; + else + return 30; +} + +/* FIX - there *must* be a simpler, less stupid way to do this!... */ +static time_t +make_time (gint date, + gint hour, + gint min) +{ + struct tm *tm; + struct tm tms; + time_t now; + gint loc_mday, loc_hour, gm_mday, gm_hour; + gint hour_diff; /* local time = UTC - hour_diff */ + gint is_dst; + + now = time(NULL); + + tm = gmtime(&now); + gm_mday = tm->tm_mday; + gm_hour = tm->tm_hour; + memcpy(&tms, tm, sizeof(struct tm)); + + tm = localtime(&now); + loc_mday = tm->tm_mday; + loc_hour = tm->tm_hour; + is_dst = tm->tm_isdst; + + /* Estimate timezone */ + if (gm_mday == loc_mday) + hour_diff = gm_hour - loc_hour; + else + if ((gm_mday == loc_mday + 1) || ((gm_mday == 1) && (loc_mday >= 27))) + hour_diff = gm_hour + (24 - loc_hour); + else + hour_diff = -((24 - gm_hour) + loc_hour); + + /* Make time */ + tms.tm_min = min; + tms.tm_sec = 0; + tms.tm_hour = hour - hour_diff; + tms.tm_mday = date; + tms.tm_isdst = is_dst; + if (tms.tm_hour < 0) { + tms.tm_hour += 24; + --tms.tm_mday; + if (tms.tm_mday < 1) { + --tms.tm_mon; + if (tms.tm_mon < 0) { + tms.tm_mon = 11; + --tms.tm_year; + } + tms.tm_mday = days_in_month(tms.tm_mon, tms.tm_year + 1900); + } + } else if (tms.tm_hour > 23) { + tms.tm_hour -= 24; + ++tms.tm_mday; + if (tms.tm_mday > days_in_month(tms.tm_mon, tms.tm_year + 1900)) { + ++tms.tm_mon; + if (tms.tm_mon > 11) { + tms.tm_mon = 0; + ++tms.tm_year; + } + tms.tm_mday = 1; + } + } + + return mktime(&tms); +} + +gboolean +metar_tok_time (char *token, + Weather *w) +{ + char sday[3], shr[3], smin[3]; + int day, hour, min; + + if (regexec (&metar_re[TIME_RE], token, 0, NULL, 0) == REG_NOMATCH) { + return FALSE; + } + + strncpy(sday, token, 2); + sday[2] = 0; + day = atoi (sday); + + strncpy (shr, token + 2, 2); + shr[2] = 0; + hour = atoi (shr); + + strncpy (smin, token + 4, 2); + smin[2] = 0; + min = atoi (smin); + + w->update = make_time (day, hour, min); + + return TRUE; +} + +#define CONST_DIGITS "0123456789" + +gboolean +metar_tok_wind (gchar *tokp, + Weather *w) +{ + char sdir[4], sspd[4], sgust[4]; + int dir, spd, gust = -1; + char *gustp; + + if (regexec(&metar_re[WIND_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + strncpy(sdir, tokp, 3); + sdir[3] = 0; + dir = (!strcmp(sdir, "VRB")) ? -1 : atoi(sdir); + + memset(sspd, 0, sizeof(sspd)); + strncpy(sspd, tokp+3, strspn(tokp+3, CONST_DIGITS)); + spd = atoi(sspd); + + gustp = strchr(tokp, 'G'); + if (gustp) { + memset(sgust, 0, sizeof(sgust)); + strncpy(sgust, gustp+1, strspn(gustp+1, CONST_DIGITS)); + gust = atoi(sgust); + } + + if ((349 <= dir) && (dir <= 11)) + w->wind = WIND_N; + else if ((12 <= dir) && (dir <= 33)) + w->wind = WIND_NNE; + else if ((34 <= dir) && (dir <= 56)) + w->wind = WIND_NE; + else if ((57 <= dir) && (dir <= 78)) + w->wind = WIND_ENE; + else if ((79 <= dir) && (dir <= 101)) + w->wind = WIND_E; + else if ((102 <= dir) && (dir <= 123)) + w->wind = WIND_ESE; + else if ((124 <= dir) && (dir <= 146)) + w->wind = WIND_SE; + else if ((147 <= dir) && (dir <= 168)) + w->wind = WIND_SSE; + else if ((169 <= dir) && (dir <= 191)) + w->wind = WIND_S; + else if ((192 <= dir) && (dir <= 213)) + w->wind = WIND_SSW; + else if ((214 <= dir) && (dir <= 236)) + w->wind = WIND_SW; + else if ((247 <= dir) && (dir <= 258)) + w->wind = WIND_WSW; + else if ((259 <= dir) && (dir <= 281)) + w->wind = WIND_W; + else if ((282 <= dir) && (dir <= 303)) + w->wind = WIND_WNW; + else if ((304 <= dir) && (dir <= 326)) + w->wind = WIND_NW; + else if ((327 <= dir) && (dir <= 348)) + w->wind = WIND_NNW; + + w->windspeed = (ESummaryWeatherWindSpeed)spd; + + return TRUE; +} + +gboolean +metar_tok_vis (gchar *tokp, + Weather *w) +{ + char *pfrac, *pend; + char sval[4]; + int val; + + if (regexec(&metar_re[VIS_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + pfrac = strchr(tokp, '/'); + pend = strstr(tokp, "SM"); + memset(sval, 0, sizeof(sval)); + + if (pfrac) { + strncpy(sval, pfrac + 1, pend - pfrac - 1); + val = atoi(sval); + w->visibility = (*tokp == 'M') ? 0.001 : (1.0 / ((ESummaryWeatherVisibility)val)); + } else { + strncpy(sval, tokp, pend - tokp); + val = atoi(sval); + w->visibility = (ESummaryWeatherVisibility)val; + } + + return TRUE; +} + +gboolean +metar_tok_cloud (gchar *tokp, + Weather *w) +{ + char stype[4], salt[4]; + int alt = -1; + + if (regexec(&metar_re[CLOUD_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + strncpy(stype, tokp, 3); + stype[3] = 0; + if (strlen(tokp) == 6) { + strncpy(salt, tokp+3, 3); + salt[3] = 0; + alt = atoi(salt); /* Altitude - currently unused */ + } + + if (!strcmp(stype, "CLR")) { + w->sky = SKY_CLEAR; + } else if (!strcmp(stype, "BKN")) { + w->sky = SKY_BROKEN; + } else if (!strcmp(stype, "SCT")) { + w->sky = SKY_SCATTERED; + } else if (!strcmp(stype, "FEW")) { + w->sky = SKY_FEW; + } else if (!strcmp(stype, "OVC")) { + w->sky = SKY_OVERCAST; + } + + return TRUE; +} + +gboolean +metar_tok_pres (gchar *tokp, + Weather *w) +{ + if (regexec(&metar_re[PRES_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + if (*tokp == 'A') { + char sintg[3], sfract[3]; + int intg, fract; + + strncpy(sintg, tokp+1, 2); + sintg[2] = 0; + intg = atoi(sintg); + + strncpy(sfract, tokp+3, 2); + sfract[2] = 0; + fract = atoi(sfract); + + w->pressure = (ESummaryWeatherPressure)intg + (((ESummaryWeatherPressure)fract)/100.0); + } else { /* *tokp == 'Q' */ + gchar spres[5]; + gint pres; + + strncpy(spres, tokp+1, 4); + spres[4] = 0; + pres = atoi(spres); + + w->pressure = PRESSURE_MBAR_TO_INCH((ESummaryWeatherPressure)pres); + } + + return TRUE; +} + +/* Relative humidity computation - thanks to <Olof.Oberg@modopaper.modogroup.com> */ + + +static inline gint +calc_humidity(gdouble temp, + gdouble dewp) +{ + gdouble esat, esurf; + + temp = TEMP_F_TO_C(temp); + dewp = TEMP_F_TO_C(dewp); + + esat = 6.11 * pow(10.0, (7.5 * temp) / (237.7 + temp)); + esurf = 6.11 * pow(10.0, (7.5 * dewp) / (237.7 + dewp)); + + return (gint)((esurf/esat) * 100.0); +} + +gboolean +metar_tok_temp (gchar *tokp, + Weather *w) +{ + gchar *ptemp, *pdew, *psep; + + if (regexec(&metar_re[TEMP_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + psep = strchr(tokp, '/'); + *psep = 0; + ptemp = tokp; + pdew = psep + 1; + + w->temp = (*ptemp == 'M') ? TEMP_C_TO_F(-atoi(ptemp+1)) : + TEMP_C_TO_F(atoi(ptemp)); + w->dew = (*pdew == 'M') ? TEMP_C_TO_F(-atoi(pdew+1)) : + TEMP_C_TO_F(atoi(pdew)); + w->humidity = calc_humidity(w->temp, w->dew); + return TRUE; +} + +gboolean +metar_tok_cond (gchar *tokp, + Weather *w) +{ + char squal[3], sphen[4]; + char *pphen; + + if (regexec(&metar_re[COND_RE], tokp, 0, NULL, 0) == REG_NOMATCH) + return FALSE; + + if ((strlen(tokp) > 3) && ((*tokp == '+') || (*tokp == '-'))) + ++tokp; /* FIX */ + + if ((*tokp == '+') || (*tokp == '-')) + pphen = tokp + 1; + else if (strlen(tokp) < 4) + pphen = tokp; + else + pphen = tokp + 2; + + memset(squal, 0, sizeof(squal)); + strncpy(squal, tokp, pphen - tokp); + squal[pphen - tokp] = 0; + + memset(sphen, 0, sizeof(sphen)); + strncpy(sphen, pphen, sizeof(sphen)); + sphen[sizeof(sphen)-1] = '\0'; + + /* Defaults */ + w->cond.qualifier = QUALIFIER_NONE; + w->cond.phenomenon = PHENOMENON_NONE; + w->cond.significant = FALSE; + + if (!strcmp(squal, "")) { + w->cond.qualifier = QUALIFIER_MODERATE; + } else if (!strcmp(squal, "-")) { + w->cond.qualifier = QUALIFIER_LIGHT; + } else if (!strcmp(squal, "+")) { + w->cond.qualifier = QUALIFIER_HEAVY; + } else if (!strcmp(squal, "VC")) { + w->cond.qualifier = QUALIFIER_VICINITY; + } else if (!strcmp(squal, "MI")) { + w->cond.qualifier = QUALIFIER_SHALLOW; + } else if (!strcmp(squal, "BC")) { + w->cond.qualifier = QUALIFIER_PATCHES; + } else if (!strcmp(squal, "PR")) { + w->cond.qualifier = QUALIFIER_PARTIAL; + } else if (!strcmp(squal, "TS")) { + w->cond.qualifier = QUALIFIER_THUNDERSTORM; + } else if (!strcmp(squal, "BL")) { + w->cond.qualifier = QUALIFIER_BLOWING; + } else if (!strcmp(squal, "SH")) { + w->cond.qualifier = QUALIFIER_SHOWERS; + } else if (!strcmp(squal, "DR")) { + w->cond.qualifier = QUALIFIER_DRIFTING; + } else if (!strcmp(squal, "FZ")) { + w->cond.qualifier = QUALIFIER_FREEZING; + } else { + g_return_val_if_fail(FALSE, FALSE); + } + + if (!strcmp(sphen, "DZ")) { + w->cond.phenomenon = PHENOMENON_DRIZZLE; + } else if (!strcmp(sphen, "RA")) { + w->cond.phenomenon = PHENOMENON_RAIN; + } else if (!strcmp(sphen, "SN")) { + w->cond.phenomenon = PHENOMENON_SNOW; + } else if (!strcmp(sphen, "SG")) { + w->cond.phenomenon = PHENOMENON_SNOW_GRAINS; + } else if (!strcmp(sphen, "IC")) { + w->cond.phenomenon = PHENOMENON_ICE_CRYSTALS; + } else if (!strcmp(sphen, "PE")) { + w->cond.phenomenon = PHENOMENON_ICE_PELLETS; + } else if (!strcmp(sphen, "GR")) { + w->cond.phenomenon = PHENOMENON_HAIL; + } else if (!strcmp(sphen, "GS")) { + w->cond.phenomenon = PHENOMENON_SMALL_HAIL; + } else if (!strcmp(sphen, "UP")) { + w->cond.phenomenon = PHENOMENON_UNKNOWN_PRECIPITATION; + } else if (!strcmp(sphen, "BR")) { + w->cond.phenomenon = PHENOMENON_MIST; + } else if (!strcmp(sphen, "FG")) { + w->cond.phenomenon = PHENOMENON_FOG; + } else if (!strcmp(sphen, "FU")) { + w->cond.phenomenon = PHENOMENON_SMOKE; + } else if (!strcmp(sphen, "VA")) { + w->cond.phenomenon = PHENOMENON_VOLCANIC_ASH; + } else if (!strcmp(sphen, "SA")) { + w->cond.phenomenon = PHENOMENON_SAND; + } else if (!strcmp(sphen, "HZ")) { + w->cond.phenomenon = PHENOMENON_HAZE; + } else if (!strcmp(sphen, "PY")) { + w->cond.phenomenon = PHENOMENON_SPRAY; + } else if (!strcmp(sphen, "DU")) { + w->cond.phenomenon = PHENOMENON_DUST; + } else if (!strcmp(sphen, "SQ")) { + w->cond.phenomenon = PHENOMENON_SQUALL; + } else if (!strcmp(sphen, "SS")) { + w->cond.phenomenon = PHENOMENON_SANDSTORM; + } else if (!strcmp(sphen, "DS")) { + w->cond.phenomenon = PHENOMENON_DUSTSTORM; + } else if (!strcmp(sphen, "PO")) { + w->cond.phenomenon = PHENOMENON_DUST_WHIRLS; + } else if (!strcmp(sphen, "+FC")) { + w->cond.phenomenon = PHENOMENON_TORNADO; + } else if (!strcmp(sphen, "FC")) { + w->cond.phenomenon = PHENOMENON_FUNNEL_CLOUD; + } else { + g_return_val_if_fail(FALSE, FALSE); + } + + if ((w->cond.qualifier != QUALIFIER_NONE) || (w->cond.phenomenon != PHENOMENON_NONE)) + w->cond.significant = TRUE; + + return TRUE; +} |