weather_report 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ == 0.0.1 2009-05-04
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/Manifest.txt ADDED
@@ -0,0 +1,14 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ PostInstall.txt
5
+ Rakefile
6
+ lib/weather_report.rb
7
+ script/console
8
+ script/console.cmd
9
+ script/destroy
10
+ script/destroy.cmd
11
+ script/generate
12
+ script/generate.cmd
13
+ test/test_helper.rb
14
+ test/test_weather_report.rb
data/PostInstall.txt ADDED
@@ -0,0 +1,2 @@
1
+
2
+ For more information on weather_report, see http://www.cordinc.com/projects/weather_report
data/README.rdoc ADDED
@@ -0,0 +1,119 @@
1
+ = weather_report
2
+
3
+ Homepage:: http://www.cordinc.com/projects/weather_report
4
+ Author:: Charles Cordingley
5
+ Copyright:: (c) 2009 Charles Cordingley
6
+ License:: MIT
7
+
8
+ == DESCRIPTION:
9
+
10
+ Connect to the BBC Backstage (http://backstage.bbc.co.uk) weather API and get weather observations and forecasts for thousands of cities worldwide. No
11
+ login is required to the BBC for use.
12
+
13
+ == TODO
14
+
15
+ * Allow weather to be shown in either metric or imperial units (currently only metric)
16
+ * Be able to seach or lookup location ids
17
+ * Add weather sources other than the BBC
18
+
19
+ == SYNOPSIS:
20
+
21
+ After requiring the library, create a WeatherReport object with a BBC weather location id:
22
+
23
+ require 'weather_report'
24
+ # 8 is the BBC Backstage weather code for London, UK
25
+ londonWeather = WeatherReport.new(8)
26
+
27
+ Then you can get the observations or forecasts for that location:
28
+
29
+ londonWeather.observation.temperature
30
+ londonWeather.forecast.for_tomorrow.max_temperature
31
+
32
+ Calls to the observation or forecast data after the first call for a location will just return return cached data. Use force_reload = true on the call to force
33
+ the data to be reloaded from the BBC.
34
+
35
+ # use the cached data
36
+ londonWeather.observation.reading_date
37
+ # reload the data
38
+ londonWeather.observation(force_reload = true).reading_date
39
+
40
+ Forecasts can be specified in a number of ways:
41
+
42
+ londonWeather.forecast.for_tomorrow.max_temperature
43
+ londonWeather.forecast.for_today.max_temperature
44
+ # also today
45
+ londonWeather.forecast.for(Date.today).max_temperature
46
+ # day after tomorrow
47
+ londonWeather.forecast.for(Date.today+2).max_temperature
48
+ # The date can also be specified as a date string
49
+ londonWeather.forecast.for("2009-05-06").max_temperature
50
+ # The underlying structure is an array, so you can just index into it. The below is the same as today
51
+ londonWeather.forecast[0].max_temperature
52
+
53
+ The full set of attributes is:
54
+
55
+ londonWeather.observation.reading_date
56
+ londonWeather.observation.name
57
+ londonWeather.observation.country
58
+ londonWeather.observation.latitude
59
+ londonWeather.observation.longtitude
60
+ londonWeather.observation.temperature
61
+ londonWeather.observation.wind_speed
62
+ londonWeather.observation.wind_direction
63
+ londonWeather.observation.humidity
64
+ londonWeather.observation.pressure
65
+ londonWeather.observation.pressure_state
66
+ londonWeather.observation.visibility
67
+ londonWeather.observation.humidity
68
+
69
+ londonWeather.forecast.reading_date
70
+ londonWeather.forecast.name
71
+ londonWeather.forecast.country
72
+ londonWeather.forecast.latitude
73
+ londonWeather.forecast.longtitude
74
+ londonWeather.forecast.for_today.date
75
+ londonWeather.forecast.for_today.max_temperature
76
+ londonWeather.forecast.for_today.min_temperature
77
+ londonWeather.forecast.for_today.wind_speed
78
+ londonWeather.forecast.for_today.wind_direction
79
+ londonWeather.forecast.for_today.humidity
80
+ londonWeather.forecast.for_today.pressure
81
+ londonWeather.forecast.for_today.visibility
82
+ londonWeather.forecast.for_today.humidity
83
+
84
+ == REQUIREMENTS:
85
+
86
+ The only external dependencies are REXML and net/http which are include as part of most Ruby installations.
87
+
88
+ == INSTALL:
89
+
90
+ The weather_report library is distributed itself as a RubyGem and is available immediately after installation.
91
+
92
+ sudo gem install weather_report
93
+
94
+ Alternately, download the gem and install manually.
95
+
96
+ == LICENSE:
97
+
98
+ (The MIT License)
99
+
100
+ Copyright (c) 2009 FIXME full name
101
+
102
+ Permission is hereby granted, free of charge, to any person obtaining
103
+ a copy of this software and associated documentation files (the
104
+ 'Software'), to deal in the Software without restriction, including
105
+ without limitation the rights to use, copy, modify, merge, publish,
106
+ distribute, sublicense, and/or sell copies of the Software, and to
107
+ permit persons to whom the Software is furnished to do so, subject to
108
+ the following conditions:
109
+
110
+ The above copyright notice and this permission notice shall be
111
+ included in all copies or substantial portions of the Software.
112
+
113
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
114
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
115
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
116
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
117
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
118
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
119
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,28 @@
1
+ %w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
2
+ require File.dirname(__FILE__) + '/lib/weather_report'
3
+
4
+ # Generate all the Rake tasks
5
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
6
+ $hoe = Hoe.new('weather_report', WeatherReport::VERSION) do |p|
7
+ p.developer('Charles Cordingley', 'inquiries at cordinc dot com')
8
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
9
+ p.post_install_message = 'PostInstall.txt' # TODO remove if post-install message not required
10
+ p.rubyforge_name = 'weather-report'
11
+ # p.extra_deps = [
12
+ # ['activesupport','>= 2.0.2'],
13
+ # ]
14
+ p.extra_dev_deps = [
15
+ ['newgem', ">= #{::Newgem::VERSION}"]
16
+ ]
17
+
18
+ p.clean_globs |= %w[**/.DS_Store tmp *.log]
19
+ path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
20
+ p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
21
+ p.rsync_args = '-av --delete --ignore-errors'
22
+ end
23
+
24
+ require 'newgem/tasks' # load /tasks/*.rake
25
+ Dir['tasks/**/*.rake'].each { |t| load t }
26
+
27
+ # TODO - want other tests/tasks run by default? Add them to the list
28
+ # task :default => [:spec, :features]
@@ -0,0 +1,221 @@
1
+ require 'net/http'
2
+ require "rexml/document"
3
+
4
+ $:.unshift(File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ # Class containing weather observations and forecasts for the location specified by id in the constructor.
8
+ class WeatherReport
9
+
10
+ VERSION = '0.0.1'
11
+
12
+ # The id is the number (1..9999) the BBC uses to identify cities for weather reports
13
+ attr_reader :id
14
+
15
+ # Raised when there is no response from the server
16
+ class NoResponseError < StandardError
17
+ end
18
+
19
+ # Raised when the data returned from BBC is not in the expected format
20
+ class FormatError < StandardError
21
+ end
22
+
23
+ # Requires a valid BBC Backstage weather id (or any call to the API will return a FormatError)
24
+ def initialize(location_id)
25
+ @id = location_id
26
+ end
27
+
28
+ # Returns the weather observation for the current id. If one is not currently loaded then this will go to the BBC Backstage API and download it.
29
+ # Alternatively, by specifying force_reload = true the observation will be loaded from the BBC regardless of whether one has already been downloaded.
30
+ def observation(force_reload = false)
31
+ @observation = WeatherReportObservation.new(fetch(observation_url())) if force_reload or @observation.nil?
32
+ @observation
33
+ end
34
+
35
+ # Returns the weather forecast for the current id. If one is not currently loaded then this will go to the BBC Backstage API and download it.
36
+ # Alternatively, by specifying force_reload = true the observation will be loaded from the BBC regardless of whether one has already been downloaded.
37
+ def forecast(force_reload = false)
38
+ @forecast = WeatherReportForecasts.new(fetch(forecast_url())) if force_reload or @forecast.nil?
39
+ @forecast
40
+ end
41
+
42
+ protected
43
+
44
+ # Fetch Response from the api
45
+ def fetch(url)
46
+ response = Net::HTTP.get_response(URI.parse(url)).body
47
+
48
+ # Check if a response was returned at all
49
+ raise(WeatherReport::NoResponseError, "WeatherReport Error: No Response.") unless response
50
+
51
+ response
52
+ end
53
+
54
+ # The url for getting current weather observations from BBC Backstage
55
+ def observation_url()
56
+ "http://news.bbc.co.uk/weather/forecast/#{@id}/ObservationsRSS.rss"
57
+ end
58
+
59
+ # The url for getting weather forecasts from BBC Backstage
60
+ def forecast_url()
61
+ "http://news.bbc.co.uk/weather/forecast/#{@id}/Next3DaysRSS.rss"
62
+ end
63
+
64
+ end
65
+
66
+ # Module to load and provide accessors for shared location specific
67
+ module Location
68
+
69
+ TITLE = /(.+) for ([\w -\.]*), ([\w -\.]*)/
70
+
71
+ attr_reader :name, :country, :latitude, :longtitude
72
+
73
+ # load the location based data (name, country, latitude, longtitude) from the backstage feed
74
+ def loadLocation(xmlDoc)
75
+ xmlDoc.elements.each("rss/channel/title") { |element|
76
+ md = TITLE.match(element.text)
77
+ @name = md[2] if md
78
+ @country = md[3] if md
79
+ }
80
+
81
+ xmlDoc.elements.each("rss/channel/item[1]/geo:lat") { |element| @latitude = element.text.to_f }
82
+ xmlDoc.elements.each("rss/channel/item[1]/geo:long") { |element| @longtitude = element.text.to_f }
83
+ end
84
+ end
85
+
86
+ # The current weather observations (at least at the time of reading - given by attribute reading_date)
87
+ class WeatherReportObservation
88
+ include Location
89
+
90
+ DESCRIPTION = /Temperature: ([-\d\.]+|N\/A|NA|\(none\))(.+)Wind Direction: ([\w -\/\(\)]*), Wind Speed: ([-\d\.]+|N\/A|NA|\(none\))mph, Relative Humidity: ([\d\.]+|N\/A|NA|\(none\))(.*), Pressure: ([\d\.]+|N\/A|NA|\(none\))mB, ([\w -\/]+), Visibility: ([\w -\/]+)/
91
+ SUMMARY = /(.+):(\W+)([\w -\/\(\)]+). (.+)/m
92
+
93
+ attr_reader :temperature, :wind_direction, :wind_speed, :visibility, :pressure, :pressure_state, :humidity, :reading_date
94
+
95
+ # Constructs the weather observation from an XML string or file containing the XML in BBC Backstage weather format
96
+ def initialize(document)
97
+ doc = REXML::Document.new document
98
+
99
+ loadLocation(doc)
100
+ @reading_date = DateTime.now
101
+ doc.elements.each("rss/channel/item[1]/title[1]") { |element|
102
+ md = SUMMARY.match(element.text)
103
+ @description = md[3]
104
+ }
105
+
106
+ doc.elements.each("rss/channel/item[1]/description[1]") { |element|
107
+ md = DESCRIPTION.match(element.text)
108
+ @temperature = md[1].to_f
109
+ @wind_direction = md[3]
110
+ @wind_speed = md[4].to_f * 1.61
111
+ @humidity = md[5].to_f
112
+ @pressure = md[7].to_f
113
+ @pressure_state = md[8]
114
+ @visibility = md[9]
115
+ }
116
+
117
+ rescue
118
+ raise WeatherReport::FormatError
119
+ end
120
+
121
+ end
122
+
123
+ # A collection of forecasts for a particular location
124
+ class WeatherReportForecasts < Array
125
+ include Location
126
+
127
+ attr_reader :reading_date
128
+
129
+ # Constructs the weather forecasts from an XML string or file containing the XML in BBC Backstage weather format
130
+ def initialize(document)
131
+ doc = REXML::Document.new document
132
+ @reading_date = DateTime.now
133
+ loadLocation(doc)
134
+ doc.elements.each("rss/channel/image/url") { |element| @image_url = element.text }
135
+
136
+ doc.elements.each("rss/channel/item/") { |element|
137
+ self << WeatherReportForecast.new(element)
138
+ }
139
+
140
+ rescue
141
+ raise WeatherReport::FormatError
142
+ end
143
+
144
+ # Returns the forecast for today, or nil is there is no such forecast.
145
+ def for_today
146
+ self.for(Date.today)
147
+ end
148
+
149
+ # Returns the forecast for tomorrow, or nil is there is no such forecast.
150
+ def for_tomorrow
151
+ self.for(Date.today+1)
152
+ end
153
+
154
+ # Returns a forecast for a day given by a Date, DateTime, Time, or a string that can be parsed to a date.
155
+ # If there is no forecast for the given date then nil is returned.
156
+ def for(date = Date.today)
157
+ date = case date.class.name
158
+ when 'String'
159
+ Date.parse(date)
160
+ when 'Date'
161
+ date
162
+ when 'DateTime'
163
+ Date.new(date.year, date.month, date.day)
164
+ when 'Time'
165
+ Date.new(date.year, date.month, date.day)
166
+ end
167
+
168
+ day = nil
169
+ self.each do |fd|
170
+ day = fd if date == fd.date
171
+ end
172
+ return day
173
+ end
174
+
175
+ # A forecast for a single day
176
+ class WeatherReportForecast
177
+
178
+ SUMMARY = /([\w -\/]+): ([\w -]+|N\/A|NA|\(none\)), Max Temp: (.*)/m
179
+ DESCRIPTION = /Max Temp: ([-\d\.]+|N\/A|NA|\(none\))(.+)Min Temp: ([-\d\.]+|N\/A|NA|\(none\))(.+)Wind Direction: ([\w -\/\(\)]*), Wind Speed: ([-\d\.]+|N\/A|NA|\(none\))mph, Visibility: ([\w -\/]+), Pressure: ([\d\.]+|N\/A|NA|\(none\))mB, Humidity: ([\d\.]+|N\/A|NA|\(none\))(.*), (.+)/m
180
+
181
+ attr_reader :max_temperature, :min_temperature, :wind_direction, :wind_speed, :visibility, :pressure, :humidity, :date
182
+
183
+ # Constructs the single day forecast from an REXML element containing the forecast in BBC Backstage weather format
184
+ def initialize(item)
185
+ item.elements.each("title[1]") { |element|
186
+ md = SUMMARY.match(element.text)
187
+ @description = md[2]
188
+ diff = day_diff(md[1])
189
+ raise(WeatherReport::FormatError, "WeatherReport Error: Day mismatch.") if diff.nil?
190
+ @date = Date.today+diff
191
+ }
192
+
193
+ item.elements.each("description[1]") { |element|
194
+ md = DESCRIPTION.match(element.text)
195
+ @max_temperature = md[1].to_f
196
+ @min_temperature = md[3].to_f
197
+ @wind_direction = md[5]
198
+ @wind_speed = md[6].to_f * 1.61
199
+ @visibility = md[7]
200
+ @pressure = md[8].to_f
201
+ @humidity = md[9].to_f
202
+ }
203
+ end
204
+
205
+ protected
206
+
207
+ # Calculate the number of days the given day name is from today's day name assuming it is no more than 5 days in the future or no further back than yesterday.
208
+ # Eg. If today is Wednesday, then if passed Tuesday this function will return -1, if passed Friday it will return 2, and if passed Wednesday it will return 0.
209
+ def day_diff(day_from)
210
+ start = Date::DAYNAMES.index(day_from.downcase.gsub!(/^[a-z]|\s+[a-z]/) { |a| a.upcase })
211
+ return if start.nil?
212
+ finish = Date.today.wday
213
+ result = start - finish
214
+ result = result+7 if result < -1
215
+ result = result-7 if result >5
216
+ result
217
+ end
218
+
219
+ end
220
+
221
+ end
data/script/console ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+ # File: script/console
3
+ irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
4
+
5
+ libs = " -r irb/completion"
6
+ # Perhaps use a console_lib to store any extra methods I may want available in the cosole
7
+ # libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
8
+ libs << " -r #{File.dirname(__FILE__) + '/../lib/weather_report.rb'}"
9
+ puts "Loading weather_report gem"
10
+ exec "#{irb} #{libs} --simple-prompt"
@@ -0,0 +1 @@
1
+ @ruby script/console %*
data/script/destroy ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/destroy'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Destroy.new.run(ARGV)
@@ -0,0 +1 @@
1
+ @ruby script/destroy %*
data/script/generate ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
3
+
4
+ begin
5
+ require 'rubigen'
6
+ rescue LoadError
7
+ require 'rubygems'
8
+ require 'rubigen'
9
+ end
10
+ require 'rubigen/scripts/generate'
11
+
12
+ ARGV.shift if ['--help', '-h'].include?(ARGV[0])
13
+ RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
14
+ RubiGen::Scripts::Generate.new.run(ARGV)
@@ -0,0 +1 @@
1
+ @ruby script/generate %*
@@ -0,0 +1,3 @@
1
+ require 'stringio'
2
+ require 'test/unit'
3
+ require File.dirname(__FILE__) + '/../lib/weather_report'
@@ -0,0 +1,115 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class TestWeatherReport < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ w = WeatherReport.new(92)
10
+ assert_not_nil(w)
11
+ assert_equal(w.id, 92)
12
+ end
13
+
14
+ def test_fine_observation
15
+ obs = WeatherReportObservation.new(File.read(File.dirname(__FILE__) + '/BBC_ObservationsRSS.rss'))
16
+ assert_not_nil(obs)
17
+ assert_equal(obs.name, "Perth")
18
+ assert_equal(obs.country, "Australia")
19
+ assert_equal(obs.latitude, -31.93)
20
+ assert_equal(obs.longtitude, 115.97)
21
+ assert_equal(obs.temperature, 15)
22
+ assert_equal(obs.wind_direction, "SW")
23
+ assert_equal(obs.wind_speed, 1.61)
24
+ assert_equal(obs.visibility, "Very good")
25
+ assert_equal(obs.pressure, 1026)
26
+ assert_equal(obs.pressure_state, "rising")
27
+ assert_equal(obs.humidity, 52)
28
+ end
29
+
30
+ def test_no_wind_observation
31
+ obs = WeatherReportObservation.new(File.read(File.dirname(__FILE__) + '/BBC_no_wind_ObservationsRSS.rss'))
32
+ assert_not_nil(obs)
33
+ assert_equal(obs.name, "Perth")
34
+ assert_equal(obs.country, "Australia")
35
+ assert_equal(obs.latitude, -31.93)
36
+ assert_equal(obs.longtitude, 115.97)
37
+ assert_equal(obs.temperature, 10)
38
+ assert_equal(obs.wind_direction, "")
39
+ assert_equal(obs.wind_speed, 0)
40
+ assert_equal(obs.visibility, "Excellent")
41
+ assert_equal(obs.pressure, 1025)
42
+ assert_equal(obs.pressure_state, "falling")
43
+ assert_equal(obs.humidity, 63)
44
+ end
45
+
46
+ def test_error_observation
47
+ assert_raise(WeatherReport::FormatError) { WeatherReportObservation.new(File.read(File.dirname(__FILE__) + '/error.rss'))}
48
+ end
49
+
50
+ def test_error_forecast
51
+ assert_raise(WeatherReport::FormatError) { WeatherReportForecasts.new(File.read(File.dirname(__FILE__) + '/error.rss'))}
52
+ end
53
+
54
+ def test_current_forecast
55
+ doc = File.read(File.dirname(__FILE__) + '/BBC_Next3DaysRSS.rss')
56
+ doc = doc.gsub("<TODAY>", Date::DAYNAMES[Date.today.wday]).gsub("<TOMORROW>", Date::DAYNAMES[(Date.today+1).wday]).gsub("<DAY_AFTER_TOMORROW>", Date::DAYNAMES[(Date.today+2).wday])
57
+ f = WeatherReportForecasts.new(doc)
58
+ assert_equal(f.name, "Perth")
59
+ assert_equal(f.country, "Australia")
60
+ assert_equal(f.latitude, -31.93)
61
+ assert_equal(f.longtitude, 115.95)
62
+
63
+ assert_equal(f.for_today.max_temperature, 28)
64
+ assert_equal(f.for_today.min_temperature, 14)
65
+ assert_equal(f.for_today.wind_direction, "ENE")
66
+ assert_equal(f.for_today.wind_speed, 9.66)
67
+ assert_equal(f.for_today.visibility, "very good")
68
+ assert_equal(f.for_today.pressure, 1026)
69
+ assert_equal(f.for_today.humidity, 30)
70
+
71
+ assert_equal(f.for_tomorrow.max_temperature, 27)
72
+ assert_equal(f.for_tomorrow.min_temperature, 14)
73
+ assert_equal(f.for_tomorrow.wind_direction, "ENE")
74
+ assert((f.for_tomorrow.wind_speed - 11.27).abs < 0.01)
75
+ assert_equal(f.for_tomorrow.visibility, "very good")
76
+ assert_equal(f.for_tomorrow.pressure, 1028)
77
+ assert_equal(f.for_tomorrow.humidity, 33)
78
+
79
+ assert_equal(f.for(Date.today+2).max_temperature, 25)
80
+ assert_equal(f.for(Date.today+2).min_temperature, 14)
81
+ assert_equal(f.for(Date.today+2).wind_direction, "ENE")
82
+ assert_equal(f.for(Date.today+2).wind_speed, 14.49)
83
+ assert_equal(f.for(Date.today+2).visibility, "very good")
84
+ assert_equal(f.for(Date.today+2).pressure, 1028)
85
+ assert_equal(f.for(Date.today+2).humidity, 37)
86
+
87
+ assert_nil(f.for(Date.today+3))
88
+ assert_nil(f.for(Date.today-1))
89
+ end
90
+
91
+ def test_shift_back_forecast
92
+ doc = File.read(File.dirname(__FILE__) + '/BBC_Next3DaysRSS.rss')
93
+ doc = doc.gsub("<TODAY>", Date::DAYNAMES[(Date.today-1).wday]).gsub("<TOMORROW>", Date::DAYNAMES[Date.today.wday]).gsub("<DAY_AFTER_TOMORROW>", Date::DAYNAMES[(Date.today+1).wday])
94
+ f = WeatherReportForecasts.new(doc)
95
+
96
+ assert_equal(f.for(Date.today-1).max_temperature, 28)
97
+ assert_equal(f.for(Date.today).max_temperature, 27)
98
+ assert_equal(f.for(Date.today+1).max_temperature, 25)
99
+ assert_nil(f.for(Date.today+2))
100
+ assert_nil(f.for(Date.today-2))
101
+ end
102
+
103
+ def test_shift_forward_forecast
104
+ doc = File.read(File.dirname(__FILE__) + '/BBC_Next3DaysRSS.rss')
105
+ doc = doc.gsub("<TODAY>", Date::DAYNAMES[(Date.today+1).wday]).gsub("<TOMORROW>", Date::DAYNAMES[(Date.today+2).wday]).gsub("<DAY_AFTER_TOMORROW>", Date::DAYNAMES[(Date.today+3).wday])
106
+ f = WeatherReportForecasts.new(doc)
107
+
108
+ assert_equal(f.for_tomorrow.max_temperature, 28)
109
+ assert_equal(f.for(Date.today+2).max_temperature, 27)
110
+ assert_equal(f.for(Date.today+3).max_temperature, 25)
111
+ assert_nil(f.for_today)
112
+ assert_nil(f.for(Date.today+4))
113
+ end
114
+
115
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weather_report
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Charles Cordingley
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-10 00:00:00 +01:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: newgem
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.3.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: hoe
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.0
34
+ version:
35
+ description: Connect to the BBC Backstage (http://backstage.bbc.co.uk) weather API and get weather observations and forecasts for thousands of cities worldwide. No login is required to the BBC for use.
36
+ email:
37
+ - inquiries at cordinc dot com
38
+ executables: []
39
+
40
+ extensions: []
41
+
42
+ extra_rdoc_files:
43
+ - History.txt
44
+ - Manifest.txt
45
+ - README.rdoc
46
+ - PostInstall.txt
47
+ files:
48
+ - History.txt
49
+ - Manifest.txt
50
+ - README.rdoc
51
+ - PostInstall.txt
52
+ - Rakefile
53
+ - lib/weather_report.rb
54
+ - script/console
55
+ - script/console.cmd
56
+ - script/destroy
57
+ - script/destroy.cmd
58
+ - script/generate
59
+ - script/generate.cmd
60
+ - test/test_helper.rb
61
+ - test/test_weather_report.rb
62
+ has_rdoc: true
63
+ homepage: "Homepage:: http://www.cordinc.com/projects/weather_report"
64
+ post_install_message: PostInstall.txt
65
+ rdoc_options:
66
+ - --main
67
+ - README.rdoc
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project: weather-report
85
+ rubygems_version: 1.3.1
86
+ signing_key:
87
+ specification_version: 2
88
+ summary: Connect to the BBC Backstage (http://backstage.bbc.co.uk) weather API and get weather observations and forecasts for thousands of cities worldwide
89
+ test_files:
90
+ - test/test_helper.rb
91
+ - test/test_weather_report.rb