[Xfce4-commits] <xfce4-weather-plugin:master> Rework code to get current weather.
Harald Judt
noreply at xfce.org
Fri Jul 13 16:50:01 CEST 2012
Updating branch refs/heads/master
to 3e338a930c21ecd707b4d3da20a74d0fa52f7a18 (commit)
from cc67b84f3104e88deb3c26263c0ccc7e5c529685 (commit)
commit 3e338a930c21ecd707b4d3da20a74d0fa52f7a18
Author: Harald Judt <h.judt at 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)
More information about the Xfce4-commits
mailing list