[Xfce4-commits] <xfce4-weather-plugin:master> Add code to collect and prepare forecast data.

Harald Judt noreply at xfce.org
Mon Jul 2 12:38:06 CEST 2012


Updating branch refs/heads/master
         to 5b6e2f5233907b0f8d3972a50efc98829a09d3da (commit)
       from 95641588512b8a9ffcc971d2d67893bdcd283312 (commit)

commit 5b6e2f5233907b0f8d3972a50efc98829a09d3da
Author: Harald Judt <h.judt at gmx.at>
Date:   Tue Jun 26 01:16:29 2012 +0200

    Add code to collect and prepare forecast data.
    
    Generate forecast data by copying point and interval data
    into an own timeslice. For this we're using intervals that
    are generally available for all days, but in case some don't
    exist, we'll search back and forward in an alternating
    pattern until a limit is reached and try to get the most
    useful data.

 panel-plugin/weather-data.c      |  197 ++++++++++++++++++++++++++++++++++++++
 panel-plugin/weather-data.h      |   15 +++
 panel-plugin/weather-parsers.c   |    2 +-
 panel-plugin/weather-parsers.h   |    2 +-
 panel-plugin/weather-translate.h |    2 +-
 5 files changed, 215 insertions(+), 3 deletions(-)

diff --git a/panel-plugin/weather-data.c b/panel-plugin/weather-data.c
index 426f331..6faf070 100644
--- a/panel-plugin/weather-data.c
+++ b/panel-plugin/weather-data.c
@@ -114,3 +114,200 @@ get_unit (xml_time *timeslice, units unit, datas type)
 	return "";
 }
 
+/*
+ * Calculate start and end of a daytime interval using given dates.
+ * We ought to take one of the intervals supplied by the XML feed,
+ * which gives the most consistent data and does not force too many
+ * searches to find something that fits. The following chosen
+ * intervals were pretty reliable for several tested locations at the
+ * time of this writing and gave reasonable results:
+ *   Morning:   08:00-14:00
+ *   Afternoon: 14:00-20:00
+ *   Evening:   20:00-02:00
+ *   Night:     02:00-08:00
+ */
+void
+get_daytime_interval(struct tm *start_t, struct tm *end_t, daytime dt)
+{
+    start_t->tm_min = end_t->tm_min = 0;
+    start_t->tm_sec = end_t->tm_sec = 0;
+    start_t->tm_isdst = end_t->tm_isdst = -1;
+	switch(dt) {
+	case MORNING:
+		start_t->tm_hour = 8;
+		end_t->tm_hour = 14;
+		break;
+	case AFTERNOON:
+		start_t->tm_hour = 14;
+		end_t->tm_hour = 20;
+		break;
+	case EVENING:
+		start_t->tm_hour = 20;
+		end_t->tm_hour = 26;
+		break;
+	case NIGHT:
+		start_t->tm_hour = 26;
+		end_t->tm_hour = 32;
+		break;
+	}
+}
+
+time_t
+time_calc(struct tm tm_time, gint year, gint month, gint day, gint hour, gint min, gint sec)
+{
+    time_t result;
+    struct tm tm_new;
+    tm_new = tm_time;
+    if (year)
+        tm_new.tm_year += year;
+    if (month)
+        tm_new.tm_mon += month;
+    if (day)
+        tm_new.tm_mday += day;
+    if (hour)
+        tm_new.tm_hour += hour;
+    if (min)
+        tm_new.tm_min += min;
+    if (sec)
+        tm_new.tm_sec += sec;
+    result = mktime(&tm_new);
+    return result;
+}
+
+time_t
+time_calc_hour(struct tm tm_time, gint hours) {
+    return time_calc(tm_time, 0, 0, 0, hours, 0, 0);
+}
+
+time_t
+time_calc_day(struct tm tm_time, gint days) {
+    return time_calc(tm_time, 0, 0, days, 0, 0, 0);
+}
+
+/*
+ * Find a timeslice that best matches the start and end times within
+ * reasonable limits.
+ */
+xml_time *
+find_timeslice(xml_weather *data, struct tm tm_start, struct tm tm_end)
+{
+    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);
+
+            hours++;
+        }
+        interval++;
+    }
+
+    return NULL;
+}
+
+/*
+ * Take point and interval data and generate one combined timeslice
+ * that provides all information needed to present a forecast.
+ */
+xml_time *
+make_combined_timeslice(xml_time *point, xml_time *interval)
+{
+    xml_time *forecast;
+	xml_location *loc;
+	gint i;
+
+    if (point == NULL || interval == NULL)
+        return NULL;
+
+	forecast = g_slice_new0(xml_time);
+	if (forecast == NULL)
+		return NULL;
+
+    loc = g_slice_new0(xml_location);
+    if (loc == NULL)
+        return forecast;
+
+    forecast->start = point->start;
+    forecast->end = interval->end;
+
+    loc->temperature_value = g_strdup(point->location->temperature_value);
+    loc->temperature_unit = g_strdup(point->location->temperature_unit);
+
+    loc->wind_dir_deg = g_strdup(point->location->wind_dir_deg);
+    loc->wind_dir_name = g_strdup(point->location->wind_dir_name);
+    loc->wind_speed_mps = g_strdup(point->location->wind_speed_mps);
+    loc->wind_speed_beaufort = g_strdup(point->location->wind_speed_beaufort);
+
+    loc->humidity_value = g_strdup(point->location->humidity_value);
+    loc->humidity_unit = g_strdup(point->location->humidity_unit);
+
+    loc->pressure_value = g_strdup(point->location->pressure_value);
+    loc->pressure_unit = g_strdup(point->location->pressure_unit);
+
+    for (i = 0; i < NUM_CLOUDINESS; i++)
+        loc->cloudiness_percent[i] = g_strdup(point->location->cloudiness_percent[i]);
+
+    loc->fog_percent = g_strdup(point->location->fog_percent);
+
+    loc->precipitation_value = g_strdup(interval->location->precipitation_value);
+    loc->precipitation_unit = g_strdup(interval->location->precipitation_unit);
+
+    loc->symbol_id = interval->location->symbol_id;
+    loc->symbol = g_strdup(interval->location->symbol);
+
+    forecast->location = loc;
+
+    return forecast;
+}
+
+/*
+ * Get forecast data for a given daytime for the day (today + day).
+ */
+xml_time *
+make_forecast_data(xml_weather *data, int day, daytime dt)
+{
+	xml_time *forecast, *point, *interval;
+	struct tm tm_now, tm_start, tm_end;
+	time_t now, start_t, end_t;
+
+	/* 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 */
+	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);
+
+	/* next find interval data */
+    interval = find_timeslice(data, tm_start, tm_end);
+
+    /* create a new timeslice with combined point and interval data */
+    forecast = make_combined_timeslice(point, interval);
+	return forecast;
+}
diff --git a/panel-plugin/weather-data.h b/panel-plugin/weather-data.h
index e4b81e5..1853af9 100644
--- a/panel-plugin/weather-data.h
+++ b/panel-plugin/weather-data.h
@@ -41,10 +41,25 @@ typedef enum {
 	METRIC
 } units;
 
+typedef enum {
+	MORNING,
+	AFTERNOON,
+	EVENING,
+	NIGHT
+} daytime;
+
 const gchar *
 get_data (xml_time *timeslice, datas type);
 const gchar *
 get_unit (xml_time *timeslice, units unit, datas type);
+time_t
+time_calc(struct tm tm_time, gint year, gint mon, gint day, gint hour, gint min, gint sec);
+time_t
+time_calc_hour(struct tm tm_time, gint hours);
+time_t
+time_calc_day(struct tm tm_time, gint days);
+xml_time *
+make_forecast_data(xml_weather *data, int day, daytime dt);
 G_END_DECLS
 
 #endif
diff --git a/panel-plugin/weather-parsers.c b/panel-plugin/weather-parsers.c
index e6dc2d4..d97cb00 100644
--- a/panel-plugin/weather-parsers.c
+++ b/panel-plugin/weather-parsers.c
@@ -282,7 +282,7 @@ static void xml_location_free(xml_location *loc)
 	g_slice_free (xml_location, loc);
 }
 
-static void xml_time_free(xml_time *timeslice)
+void xml_time_free(xml_time *timeslice)
 {
   xml_location_free(timeslice->location);
   g_slice_free (xml_time, timeslice);
diff --git a/panel-plugin/weather-parsers.h b/panel-plugin/weather-parsers.h
index b461f90..d432507 100644
--- a/panel-plugin/weather-parsers.h
+++ b/panel-plugin/weather-parsers.h
@@ -78,7 +78,6 @@ typedef struct
 }
 xml_weather;
 
-
 xml_weather *parse_weather (xmlNode * cur_node);
 
 void parse_time (xmlNode * cur_node, xml_weather * data);
@@ -88,6 +87,7 @@ void parse_location (xmlNode * cur_node, xml_location *location);
 xml_time *get_timeslice(xml_weather *data, time_t start, time_t end);
 xml_time *get_current_timeslice(xml_weather *data, gboolean interval);
 
+void xml_time_free(xml_time *timeslice);
 void xml_weather_free (xml_weather * data);
 
 G_END_DECLS
diff --git a/panel-plugin/weather-translate.h b/panel-plugin/weather-translate.h
index a63edcc..831f4f7 100644
--- a/panel-plugin/weather-translate.h
+++ b/panel-plugin/weather-translate.h
@@ -36,7 +36,7 @@ gchar *translate_day (gint);
 
 gchar *translate_wind_direction (const gchar *);
 
-gchar *translate_wind_speed (xml_time *timeslice, const gchar *, units);
+gchar *translate_wind_speed (xml_time *, const gchar *, units);
 
 gchar *translate_time (const gchar *);
 


More information about the Xfce4-commits mailing list