Updating branch refs/heads/master to 3e338a930c21ecd707b4d3da20a74d0fa52f7a18 (commit) from cc67b84f3104e88deb3c26263c0ccc7e5c529685 (commit)
commit 3e338a930c21ecd707b4d3da20a74d0fa52f7a18 Author: Harald Judt <h.j...@gmx.at> Date: Tue Jul 10 13:30:58 2012 +0200 Rework code to get current weather. For future plans we need to rework the code which gets data about the current weather. We do this in a manner similar to getting data for a forecast, only this time we search for the shortest interval possible, preferring a timeslice near the current time. While this commit won't break compilation, it introduces memory leaks which will be solved in subsequent commits. panel-plugin/weather-data.c | 130 ++++++++++++++++++++++++++++------------ panel-plugin/weather-parsers.c | 72 ++++++++++++---------- 2 files changed, 131 insertions(+), 71 deletions(-) diff --git a/panel-plugin/weather-data.c b/panel-plugin/weather-data.c index 9a9a5eb..f42aa8d 100644 --- a/panel-plugin/weather-data.c +++ b/panel-plugin/weather-data.c @@ -215,6 +215,7 @@ time_calc(struct tm tm_time, gint year, gint month, gint day, gint hour, gint mi time_t result; struct tm tm_new; tm_new = tm_time; + tm_new.tm_isdst = -1; if (year) tm_new.tm_year += year; if (month) @@ -242,43 +243,82 @@ time_calc_day(struct tm tm_time, gint days) { } /* - * Find a timeslice that best matches the start and end times within - * reasonable limits. + * Find timeslice of the given interval near start and end + * times. Shift maximum prev_hours_limit hours into the past and + * next_hours_limit hours into the future. */ xml_time * -find_timeslice(xml_weather *data, struct tm tm_start, struct tm tm_end) +find_timeslice(xml_weather *data, struct tm tm_start, struct tm tm_end, + gint prev_hours_limit, gint next_hours_limit) { - time_t start_t, end_t; - gint hours, hours_limit = 3, interval = 0, interval_limit; - - /* first search for intervals of the same length */ - start_t = mktime(&tm_start); - end_t = mktime(&tm_end); - interval_limit = (gint) (difftime(end_t, start_t) / 3600); - - while (interval <= interval_limit) { - hours = 0; - while (hours <= hours_limit) { - /* check with previous hours */ - start_t = time_calc_hour(tm_start, 0 - hours); - end_t = time_calc_hour(tm_end, 0 - hours - interval); - - if (has_timeslice(data, start_t, end_t)) - return get_timeslice(data, start_t, end_t); - - /* check with later hours */ - start_t = time_calc_hour(tm_start, hours); - end_t = time_calc_hour(tm_end, hours - interval); - - if (has_timeslice(data, start_t, end_t)) - return get_timeslice(data, start_t, end_t); + time_t start_t, end_t; + gint hours = 0; + + /* set start and end times to the exact hour */ + tm_end.tm_min = tm_start.tm_min = 0; + tm_end.tm_sec = tm_start.tm_sec = 0; + + while (hours >= prev_hours_limit && hours <= next_hours_limit) { + /* check previous hours */ + if ((0 - hours) >= prev_hours_limit) { + start_t = time_calc_hour(tm_start, 0 - hours); + end_t = time_calc_hour(tm_end, 0 - hours); + + if (has_timeslice(data, start_t, end_t)) + return get_timeslice(data, start_t, end_t); + } + + /* check later hours */ + if (hours != 0 && hours <= next_hours_limit) { + start_t = time_calc_hour(tm_start, hours); + end_t = time_calc_hour(tm_end, hours); + + if (has_timeslice(data, start_t, end_t)) + return get_timeslice(data, start_t, end_t); + } + hours++; + } + return NULL; +} - hours++; - } - interval++; - } +/* + * Find the timeslice with the shortest interval near the given start and end times + */ +xml_time * +find_shortest_timeslice(xml_weather *data, struct tm tm_start, struct tm tm_end, + gint prev_hours_limit, gint next_hours_limit, gint interval_limit) +{ + xml_time *interval_data; + time_t start_t, end_t; + gint hours, interval; + + /* set start and end times to the exact hour */ + tm_end.tm_min = tm_start.tm_min = 0; + tm_end.tm_sec = tm_start.tm_sec = 0; + + start_t = mktime(&tm_start); + end_t = mktime(&tm_end); + + tm_start = *localtime(&start_t); + tm_end = *localtime(&end_t); + + /* minimum interval is provided by tm_start and tm_end */ + interval = (gint) (difftime(end_t, start_t) / 3600); + + while (interval <= interval_limit) { + interval_data = find_timeslice(data, tm_start, tm_end, + prev_hours_limit, next_hours_limit); + if (interval_data != NULL) + return interval_data; + + interval++; + start_t = mktime(&tm_start); + end_t = time_calc_hour(tm_end, interval); + tm_start = *localtime(&start_t); + tm_end = *localtime(&end_t); + } - return NULL; + return NULL; } /* @@ -346,29 +386,41 @@ make_combined_timeslice(xml_time *point, xml_time *interval) xml_time * make_forecast_data(xml_weather *data, int day, daytime dt) { - xml_time *forecast, *point, *interval; + xml_time *forecast, *point_data, *interval_data; struct tm tm_now, tm_start, tm_end; time_t now, start_t, end_t; + gint interval; /* initialize times to the current day */ time(&now); tm_start = *localtime(&now); tm_end = *localtime(&now); - /* calculate daytime interval start and end times for the requested day */ + /* calculate daytime interval start and end times for the requested day */ tm_start.tm_mday += day; tm_end.tm_mday += day; get_daytime_interval(&tm_start, &tm_end, dt); start_t = mktime(&tm_start); end_t = mktime(&tm_end); - /* find point data */ - point = find_timeslice(data, tm_start, tm_start); + /* find point data using a maximum variance of ±3 hours*/ + point_data = find_timeslice(data, tm_start, tm_start, -3, 3); + if (point_data == NULL) + return NULL; - /* next find interval data */ - interval = find_timeslice(data, tm_start, tm_end); + /* next find biggest possible (limited by daytime) interval data + using a maximum deviation of ±3 hours */ + while ((interval = (gint) (difftime(end_t, start_t) / 3600)) > 0) { + interval_data = find_timeslice(data, tm_start, tm_end, -3, 3); + if (interval_data != NULL) + break; + end_t = time_calc_hour(tm_end, -1); + tm_end = *localtime(&tm_end); + } + if (interval_data == NULL) + return NULL; /* create a new timeslice with combined point and interval data */ - forecast = make_combined_timeslice(point, interval); + forecast = make_combined_timeslice(point_data, interval_data); return forecast; } diff --git a/panel-plugin/weather-parsers.c b/panel-plugin/weather-parsers.c index f4f29bc..415e83f 100644 --- a/panel-plugin/weather-parsers.c +++ b/panel-plugin/weather-parsers.c @@ -158,40 +158,48 @@ xml_time *get_timeslice(xml_weather *data, time_t start, time_t end) return data->timeslice[data->num_timeslices - 1]; } -xml_time *get_current_timeslice(xml_weather *data, gboolean interval) +xml_time *get_current_timeslice(xml_weather *data, gboolean need_interval) { - time_t now = time(NULL); - int closest = -1; - int min_found = 7 * 24 * 3600; - int i; - - if (data == NULL) - return NULL; - - for (i = 0; i < data->num_timeslices; i++) { - if (interval != - (data->timeslice[i]->start != data->timeslice[i]->end)) - continue; - if (data->timeslice[i]->start <= now - && data->timeslice[i]->end >= now) - return data->timeslice[i]; - /* we also search for the closest before */ - if (data->timeslice[i]->end < now - && data->timeslice[i]->end - now < min_found) { - min_found = data->timeslice[i]->end - now; - closest = i; - } - /* and after */ - if (data->timeslice[i]->start > now - && data->timeslice[i]->start - now < min_found) { - min_found = data->timeslice[i]->start - now; - closest = i; - } - } - if (closest != -1) - return data->timeslice[closest]; + xml_time *forecast, *point_data, *interval_data; + struct tm tm_now, tm_start, tm_end; + time_t now, start_t, end_t; + gint interval; + + /* get the current time */ + time(&now); + tm_now = *localtime(&now); + + /* find nearest point data, starting with the current hour, with a + * deviation of 1 hour into the past and 6 hours into the future */ + point_data = find_timeslice(data, tm_now, tm_now, -1, 6); + if (point_data == NULL) + return NULL; + + /* now search for the nearest and shortest interval data + * available, using a maximum interval of 6 hours */ + tm_end = tm_start = tm_now; + start_t = mktime(&tm_start); + + /* set interval to 1 hour as minimum, we don't want to retrieve point data */ + end_t = time_calc_hour(tm_end, 1); + tm_end = *localtime(&end_t); + + /* We want to keep the hour deviation as small as possible, + * so let's try an interval with ±1 hour deviation first */ + interval_data = find_shortest_timeslice(data, tm_start, tm_end, -1, 1, 6); + if (interval_data == NULL) { + /* in case we were unsuccessful we might need to enlarge the search radius */ + interval_data = find_shortest_timeslice(data, tm_start, tm_end, -3, 3, 6); + if (interval_data == NULL) + /* and maybe it's necessary to try even harder... */ + interval_data = find_shortest_timeslice(data, tm_start, tm_end, -3, 6, 6); + } + if (interval_data == NULL) + return NULL; - return NULL; + /* create a new timeslice with combined point and interval data */ + forecast = make_combined_timeslice(point_data, interval_data); + return forecast; } void parse_location (xmlNode * cur_node, xml_location *loc) _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits