weather_fetcher 0.0.1 → 0.0.2

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.
Files changed (36) hide show
  1. data/Gemfile +3 -1
  2. data/Gemfile.lock +10 -4
  3. data/README.rdoc +29 -40
  4. data/Rakefile +10 -0
  5. data/VERSION +1 -1
  6. data/lib/weather_fetcher/fetcher.rb +28 -0
  7. data/lib/weather_fetcher/provider_list.rb +2 -2
  8. data/lib/weather_fetcher/providers/html_based/interia_pl.rb +2 -2
  9. data/lib/weather_fetcher/providers/html_based/onet_pl.rb +5 -3
  10. data/lib/weather_fetcher/providers/html_based/world_weather_online.rb +105 -0
  11. data/lib/weather_fetcher/providers/html_based/wp_pl.rb +2 -2
  12. data/lib/weather_fetcher/providers/{html_based.rb → html_based_provider.rb} +18 -4
  13. data/lib/weather_fetcher/providers/metar/all_met_sat.rb +24 -0
  14. data/lib/weather_fetcher/providers/metar/aviation_weather.rb +29 -0
  15. data/lib/weather_fetcher/providers/metar/noaa.rb +23 -0
  16. data/lib/weather_fetcher/providers/metar/wunderground.rb +24 -0
  17. data/lib/weather_fetcher/providers/metar_provider.rb +64 -0
  18. data/lib/weather_fetcher/providers/provider.rb +30 -4
  19. data/lib/weather_fetcher/providers.rb +9 -2
  20. data/lib/weather_fetcher/server.rb +10 -0
  21. data/lib/weather_fetcher/utils/time.rb +55 -0
  22. data/lib/weather_fetcher/weather_data.rb +33 -0
  23. data/lib/weather_fetcher.rb +5 -0
  24. metadata +86 -111
  25. data/.document +0 -5
  26. data/.rspec +0 -1
  27. data/spec/fixtures/interia_pl.yml +0 -6
  28. data/spec/fixtures/onet_pl.yml +0 -6
  29. data/spec/fixtures/weather.yml +0 -8
  30. data/spec/fixtures/wp_pl.yml +0 -6
  31. data/spec/providers/interia_pl_spec.rb +0 -14
  32. data/spec/providers/onet_pl_spec.rb +0 -14
  33. data/spec/providers/wp_pl_spec.rb +0 -14
  34. data/spec/spec_helper.rb +0 -17
  35. data/spec/weather_fetcher_spec.rb +0 -26
  36. data/weather_fetcher.gemspec +0 -77
data/Gemfile CHANGED
@@ -1,9 +1,11 @@
1
1
  source "http://rubygems.org"
2
2
 
3
+ gem "simple_metar_parser", ">= 0.0.1"
4
+
3
5
  group :development do
4
6
  gem "rspec", "~> 2.3.0"
5
7
  gem "bundler", "~> 1.0.0"
6
8
  gem "jeweler", "~> 1.6.4"
7
- gem "rcov", ">= 0"
9
+ gem 'simplecov', :require => false, :group => :test
8
10
  gem "rdoc"
9
11
  end
data/Gemfile.lock CHANGED
@@ -7,10 +7,10 @@ GEM
7
7
  bundler (~> 1.0)
8
8
  git (>= 1.2.5)
9
9
  rake
10
- json (1.6.1)
10
+ json (1.6.5)
11
+ multi_json (1.1.0)
11
12
  rake (0.9.2.2)
12
- rcov (0.9.11)
13
- rdoc (3.11)
13
+ rdoc (3.12)
14
14
  json (~> 1.4)
15
15
  rspec (2.3.0)
16
16
  rspec-core (~> 2.3.0)
@@ -20,6 +20,11 @@ GEM
20
20
  rspec-expectations (2.3.0)
21
21
  diff-lcs (~> 1.1.2)
22
22
  rspec-mocks (2.3.0)
23
+ simple_metar_parser (0.0.1)
24
+ simplecov (0.6.1)
25
+ multi_json (~> 1.0)
26
+ simplecov-html (~> 0.5.3)
27
+ simplecov-html (0.5.3)
23
28
 
24
29
  PLATFORMS
25
30
  ruby
@@ -27,6 +32,7 @@ PLATFORMS
27
32
  DEPENDENCIES
28
33
  bundler (~> 1.0.0)
29
34
  jeweler (~> 1.6.4)
30
- rcov
31
35
  rdoc
32
36
  rspec (~> 2.3.0)
37
+ simple_metar_parser (>= 0.0.1)
38
+ simplecov
data/README.rdoc CHANGED
@@ -10,49 +10,38 @@ Wp.pl and Interia.pl.
10
10
  There is simple 'how to use' code below. _defs_ is Hash object with proper data. Refactoring is on
11
11
  the way, so read this file later.
12
12
 
13
+ Please check spec/fetcher_spec.rb for code sample, and spec/fixtures/main.yml for parameters.
13
14
 
14
- = Onet.pl
15
+ = Definitions
15
16
 
16
- weathers = WeatherFetcher::Provider::OnetPl.new(defs).fetch
17
-
18
- Where _defs_ is something like this:
19
-
20
- - :url: 'http://pogoda.onet.pl/0,846,38,,,inowroclaw,miasto.html'
21
- :city: 'Inowrocław'
17
+ - :name: 'Poznań'
22
18
  :country: 'Poland'
23
- :coord:
24
- :lat: 52.799264
25
- :lon: 18.259935
26
-
27
-
28
- == Wp.pl
29
-
30
- weathers = WeatherFetcher::Provider::WpPl.new(defs).fetch
31
-
32
- Where _defs_ is something like this:
33
-
34
- - :url: 'http://pogoda.wp.pl/miasto,bydgoszcz,mid,1201023,mi.html'
35
- :city: 'Bydgoszcz'
36
- :country: 'Poland'
37
- :coord:
38
- :lat: 53.128893
39
- :lon: 18.006363
40
-
41
-
42
- == Interia.pl
43
-
44
- weathers = WeatherFetcher::Provider::InteriaPl.new(defs).fetch
45
-
46
- Where _defs_ is something like this:
47
-
48
- - :url: 'http://pogoda.interia.pl/miasta?id=11721'
49
- :city: 'Inowrocław'
50
- :country: 'Poland'
51
- :coord:
52
- :lat: 52.799264
53
- :lon: 18.259935
54
-
55
-
19
+ :metar: 'EPPO'
20
+ :coords:
21
+ :lat: 52.411048,
22
+ :lon: 16.928329
23
+ :classes:
24
+ OnetPl:
25
+ :url: 'http://pogoda.onet.pl/0,198,38,poznan,miasto.html'
26
+ WpPl:
27
+ :url: 'http://pogoda.wp.pl/miasto,poznan,mid,1201201,mi.html'
28
+ InteriaPl:
29
+ :url: 'http://pogoda.interia.pl/miasta?id=11875'
30
+ WorldWeatherOnline:
31
+ :key: 'api key'
32
+
33
+ = Fetching
34
+
35
+ result = WeatherFetcher::Fetcher.fetch(@defs)
36
+
37
+ = Providers
38
+
39
+ * Onet.pl
40
+ * Wp.pl
41
+ * Interia.pl
42
+ * WorldWeatherOnline (free api key required)
43
+ * and 4 metar providers
44
+
56
45
  == Contributing to weather_fetcher
57
46
 
58
47
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
data/Rakefile CHANGED
@@ -22,6 +22,10 @@ Jeweler::Tasks.new do |gem|
22
22
  gem.email = "bobikx@poczta.fm"
23
23
  gem.authors = ["Aleksander Kwiatkowski"]
24
24
  # dependencies defined in Gemfile
25
+
26
+ gem.files = FileList[
27
+ "[A-Z]*", "{bin,generators,lib,test}/**/*"
28
+ ]
25
29
  end
26
30
  Jeweler::RubygemsDotOrgTasks.new
27
31
 
@@ -48,3 +52,9 @@ Rake::RDocTask.new do |rdoc|
48
52
  rdoc.rdoc_files.include('README*')
49
53
  rdoc.rdoc_files.include('lib/**/*.rb')
50
54
  end
55
+
56
+ desc "Run RSpec with code coverage"
57
+ task :coverage do
58
+ `rake spec COVERAGE=true`
59
+ #`open coverage/index.html`
60
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 0.0.2
@@ -0,0 +1,28 @@
1
+ # Fetcher
2
+ module WeatherFetcher
3
+ class Fetcher
4
+
5
+ def self.fetch(p)
6
+ require 'yaml'
7
+ classes = ProviderList.providers
8
+ result = Array.new
9
+
10
+ classes.each do |c|
11
+ instance = c.new(p)
12
+ instance.fetch
13
+ result += instance.weathers
14
+ end
15
+
16
+ return result
17
+ end
18
+
19
+ def self.represent_result(result)
20
+ puts result.inspect
21
+ data = result.sort{|r,s| r.time_from <=> s.time_from}
22
+ data.each do |d|
23
+ puts "#{d.time_from} #{d.temperature} #{d.wind}"
24
+ end
25
+ end
26
+
27
+ end
28
+ end
@@ -1,8 +1,8 @@
1
1
  module WeatherFetcher
2
2
  class ProviderList
3
3
  def self.providers
4
- classes = WeatherFetcher::Provider.constants - ['TYPE']
5
- classes.collect{|c| WeatherFetcher::Provider.const_get c}
4
+ classes = WeatherFetcher::Provider.constants
5
+ classes.collect{|c| WeatherFetcher::Provider.const_get c}.select{|c| c.kind_of? Class}
6
6
  end
7
7
 
8
8
  end
@@ -1,14 +1,14 @@
1
1
  #encoding: utf-8
2
2
 
3
3
  module WeatherFetcher
4
- class Provider::InteriaPl < HtmlBased
4
+ class Provider::InteriaPl < HtmlBasedProvider
5
5
 
6
6
  def self.provider_name
7
7
  "Interia.pl"
8
8
  end
9
9
 
10
10
  def process(string)
11
- @weathers += _process(string)
11
+ WeatherData.factory( _process(string) )
12
12
  end
13
13
 
14
14
  # Process response body and rip out weather data
@@ -1,15 +1,17 @@
1
1
  #encoding: utf-8
2
2
 
3
3
  module WeatherFetcher
4
- class Provider::OnetPl < HtmlBased
4
+ class Provider::OnetPl < HtmlBasedProvider
5
5
 
6
6
  def self.provider_name
7
7
  "Onet.pl"
8
8
  end
9
9
 
10
10
  def process(string)
11
- @weathers += _process_details(string)
12
- @weathers += _process_daily(string)
11
+ a = Array.new
12
+ a += WeatherData.factory( _process_details(string) )
13
+ a += WeatherData.factory( _process_daily(string) )
14
+ return a
13
15
  end
14
16
 
15
17
  # Process response body and rip out weather data, details
@@ -0,0 +1,105 @@
1
+ #encoding: utf-8
2
+
3
+ require 'json'
4
+
5
+ module WeatherFetcher
6
+ class Provider::WorldWeatherOnline < HtmlBasedProvider
7
+ def self.provider_name
8
+ "WorldWeatherOnline"
9
+ end
10
+
11
+ # This provider required API key
12
+ def self.api=(_api)
13
+ @@api = _api
14
+ end
15
+
16
+ def self.api
17
+ @@api
18
+ end
19
+
20
+ # Url for current provider
21
+ def url(p)
22
+ "http://free.worldweatheronline.com/feed/weather.ashx?key=#{@@api}&q=#{p[:coords][:lat]},#{p[:coords][:lon]}&num_of_days=2&format=json"
23
+ end
24
+
25
+ def can_fetch?(p)
26
+ return false if not defined? @@api
27
+
28
+ begin
29
+ url(p).nil? == false
30
+ rescue
31
+ false
32
+ end
33
+ end
34
+
35
+ def process(string)
36
+ result = JSON.parse(string)
37
+
38
+ # weather archives as processing output
39
+ weather_archives = Array.new
40
+
41
+ # fix for empty response
42
+ return if result.nil? or result["data"].nil? or result["data"]["current_condition"].nil?
43
+
44
+ # current conditions
45
+ current = result["data"]["current_condition"].first
46
+ current_time = Time.create_time_from_string_12_utc(nil, current["observation_time"])
47
+
48
+ h = process_node(current)
49
+ h.merge(
50
+ {
51
+ :time_created => Time.now,
52
+ :time_from => current_time - 3600,
53
+ :time_to => current_time
54
+ }
55
+ )
56
+ weather_archives << h
57
+
58
+ # prediction
59
+ predictions = result["data"]["weather"]
60
+ predictions.each do |p|
61
+ h = process_node(p)
62
+ h[:pressure] = nil
63
+
64
+ # create 2 records using tempMinC and tempMaxC
65
+ hl = h.merge(
66
+ {
67
+ :time_created => Time.now,
68
+ :time_from => Time.create_time_from_string(p["date"], "0:00") - 4 * 3600,
69
+ :time_to => Time.create_time_from_string(p["date"], "0:00") + 8 * 3600,
70
+ :temperature => p["tempMinC"].to_i
71
+ }
72
+ )
73
+ weather_archives << hl
74
+
75
+ # and high
76
+ hh = h.merge(
77
+ {
78
+ :time_from => Time.create_time_from_string(p["date"], "0:00") + 8 * 3600,
79
+ :time_to => Time.create_time_from_string(p["date"], "0:00") + 20 * 3600,
80
+ :temperature => p["tempMaxC"].to_i
81
+ }
82
+ )
83
+ weather_archives << hh
84
+
85
+ end
86
+
87
+ return weather_archives.collect { |w| WeatherData.factory(w) }
88
+
89
+ end
90
+
91
+
92
+ # Process json node to Hash for AR
93
+ def process_node(node)
94
+ return {
95
+ :temperature => node["temp_C"].to_i,
96
+ :wind => node["windspeedKmph"].to_f / 3.6,
97
+ :pressure => node["pressure"].to_f / 3.6,
98
+ :rain => node["precipMM"].to_f / 3.6,
99
+ :snow => nil,
100
+ :weather_provider_id => @id
101
+ }
102
+ end
103
+
104
+ end
105
+ end
@@ -1,14 +1,14 @@
1
1
  #encoding: utf-8
2
2
 
3
3
  module WeatherFetcher
4
- class Provider::WpPl < HtmlBased
4
+ class Provider::WpPl < HtmlBasedProvider
5
5
 
6
6
  def self.provider_name
7
7
  "Interia.pl"
8
8
  end
9
9
 
10
10
  def process(string)
11
- @weathers += _process(string)
11
+ return WeatherData.factory( _process(string) )
12
12
  end
13
13
 
14
14
  # Process response body and rip out weather data
@@ -2,14 +2,15 @@ require 'net/http'
2
2
 
3
3
  # All ugly providers who parse even uglier html code and rip off data
4
4
  module WeatherFetcher
5
- class HtmlBased < Provider
5
+ class HtmlBasedProvider < Provider
6
6
 
7
7
  TYPE = :html_based
8
8
 
9
9
  # Get processed weather for one definition
10
- def fetch_and_process_single(d)
11
- url = d[:url]
12
- body = fetch_url(url)
10
+ def fetch_and_process_single(p)
11
+ return nil unless can_fetch?(p)
12
+
13
+ body = fetch_url(url(p))
13
14
  processed = process(body)
14
15
  return processed
15
16
  end
@@ -19,5 +20,18 @@ module WeatherFetcher
19
20
  return Net::HTTP.get(URI.parse(url))
20
21
  end
21
22
 
23
+ # Url for current provider
24
+ def url(p)
25
+ provider_params(p)[:url]
26
+ end
27
+
28
+ def can_fetch?(p)
29
+ begin
30
+ url(p).nil? == false
31
+ rescue
32
+ false
33
+ end
34
+ end
35
+
22
36
  end
23
37
  end
@@ -0,0 +1,24 @@
1
+ #encoding: utf-8
2
+
3
+ module WeatherFetcher
4
+ class Provider::AllMetSat < MetarProvider
5
+
6
+ def url_for_metar(metar_city)
7
+ u = "http://pl.allmetsat.com/metar-taf/polska.php?icao=#{metar_city.upcase}"
8
+ return u
9
+ end
10
+
11
+ def process(string)
12
+ reg = /<b>METAR:<\/b>([^<]*)<br>/
13
+ string = string.scan(reg).first.first
14
+ string.gsub!(/\n/, ' ')
15
+ string.gsub!(/\t/, ' ')
16
+ string.gsub!(/\s{2,}/, ' ')
17
+ string.strip
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+
@@ -0,0 +1,29 @@
1
+ #encoding: utf-8
2
+
3
+ module WeatherFetcher
4
+ class Provider::AviationWeather < MetarProvider
5
+
6
+ def url_for_metar(metar_city)
7
+ u = "http://aviationweather.gov/adds/metars/index.php?submit=1&station_ids=#{metar_city.upcase}"
8
+ return u
9
+ end
10
+
11
+ def process(string)
12
+ reg = /\">([^<]*)<\/FONT>/
13
+ data = string.scan(reg).first
14
+ if not data.nil? and not data.first.nil?
15
+ string = data.first
16
+ string.gsub!(/\n/, ' ')
17
+ string.gsub!(/\t/, ' ')
18
+ string.gsub!(/\s{2,}/, ' ')
19
+ string.strip
20
+ end
21
+
22
+ @metars
23
+ end
24
+
25
+ end
26
+
27
+ end
28
+
29
+
@@ -0,0 +1,23 @@
1
+ #encoding: utf-8
2
+
3
+ module WeatherFetcher
4
+ class Provider::Noaa < MetarProvider
5
+
6
+ def url_for_metar(metar_city)
7
+ u = "http://weather.noaa.gov/pub/data/observations/metar/stations/#{metar_city.upcase}.TXT"
8
+ return u
9
+ end
10
+
11
+ def process(string)
12
+ string.gsub!(/\d{4}\/\d{1,2}\/\d{1,2} \d{1,2}\:\d{1,2}\s*/, ' ')
13
+ string.gsub!(/\n/, ' ')
14
+ string.gsub!(/\t/, ' ')
15
+ string.gsub!(/\s{2,}/, ' ')
16
+ string.strip
17
+ end
18
+
19
+ end
20
+
21
+ end
22
+
23
+
@@ -0,0 +1,24 @@
1
+ #encoding: utf-8
2
+
3
+ module WeatherFetcher
4
+ class Provider::Wunderground < MetarProvider
5
+
6
+ def url_for_metar(metar_city)
7
+ u = "http://www.wunderground.com/Aviation/index.html?query=#{metar_city.upcase}"
8
+ return u
9
+ end
10
+
11
+ def process(string)
12
+ reg = /<div class=\"textReport\">\s*METAR\s*([^<]*)<\/div>/
13
+ string = string.scan(reg).first.first
14
+ string.gsub!(/\n/, ' ')
15
+ string.gsub!(/\t/, ' ')
16
+ string.gsub!(/\s{2,}/, ' ')
17
+ string.strip
18
+ end
19
+
20
+ end
21
+
22
+ end
23
+
24
+
@@ -0,0 +1,64 @@
1
+ require 'simple_metar_parser'
2
+
3
+ # All ugly providers who parse even uglier html code and rip off data
4
+ module WeatherFetcher
5
+ class MetarProvider < HtmlBasedProvider
6
+
7
+ TYPE = :metar
8
+
9
+ # Get processed weather for one definition
10
+ def fetch_and_process_single(p)
11
+ return nil unless can_fetch?(p)
12
+
13
+ url = url_for_metar(metar(p))
14
+ body = fetch_url(url)
15
+ metars = process(body)
16
+ metars = [metars] unless metars.kind_of?(Array)
17
+ processed = Array.new
18
+
19
+ metars.each do |m|
20
+ m = SimpleMetarParser::Parser.parse(m)
21
+
22
+ if m.valid?
23
+ processed << {
24
+ :time_created => Time.now,
25
+ :time_from => m.time_from,
26
+ :time_to => m.time_to,
27
+ :temperature => m.temperature.degrees,
28
+ :pressure => m.pressure.hpa,
29
+ :wind_kmh => m.wind.kmh,
30
+ :wind => m.wind.mps,
31
+ :snow_metar => m.specials.snow_metar,
32
+ :rain_metar => m.specials.rain_metar,
33
+ :provider => self.class.provider_name
34
+ }
35
+ end
36
+
37
+ end
38
+
39
+ return WeatherData.factory(processed)
40
+ end
41
+
42
+ def self.provider_name
43
+ "MetarProvider"
44
+ end
45
+
46
+ def url_for_metar(metar_city)
47
+ raise 'Not implemented'
48
+ end
49
+
50
+ # Metar
51
+ def metar(p)
52
+ p[:metar]
53
+ end
54
+
55
+ def can_fetch?(p)
56
+ begin
57
+ metar(p).nil? == false
58
+ rescue
59
+ false
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -7,7 +7,7 @@ module WeatherFetcher
7
7
  # Create an instance, definitions can be set here
8
8
  def initialize(_defs = Array.new)
9
9
  @weathers = Array.new
10
- self.defs= _defs
10
+ self.defs = _defs
11
11
  end
12
12
 
13
13
  attr_reader :weathers
@@ -39,26 +39,52 @@ module WeatherFetcher
39
39
 
40
40
  # Name of provider, should be overrode
41
41
  def self.provider_name
42
- raise 'Not implemented'
42
+ raise NotImplementedError
43
43
  end
44
44
 
45
45
  # Fetch everything from definitions (defs)
46
46
  def fetch
47
47
  a = Array.new
48
48
  defs.each do |d|
49
- a += fetch_and_process_single(d)
49
+ p = fetch_and_process_single(d)
50
+ a += p unless p.nil?
50
51
  end
52
+ # add to result array
53
+ @weathers += a
54
+
51
55
  return a
52
56
  end
53
57
 
54
58
  # Fetch single definition
55
59
  def fetch_and_process_single(d)
56
- url = d[:url]
60
+ return nil unless can_fetch?
61
+
57
62
  body = fetch_url(url)
58
63
  processed = process(body)
59
64
  return processed
60
65
  end
61
66
 
67
+ # All parameters are available and we can fetch
68
+ def can_fetch?(p = nil)
69
+ raise NotImplementedError
70
+ end
71
+
72
+ def url(p = nil)
73
+ raise NotImplementedError
74
+ end
75
+
76
+ def self.short_class_name
77
+ self.to_s.gsub(/^.*::/, '')
78
+ end
79
+
80
+ def short_class_name
81
+ self.class.short_class_name
82
+ end
83
+
84
+ # Return Hash of parameters used for current provider
85
+ def provider_params(p)
86
+ return p[:classes][short_class_name]
87
+ end
62
88
 
63
89
  end
64
90
  end
@@ -1,8 +1,15 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
3
  require 'providers/provider'
4
- require 'providers/html_based'
5
4
 
5
+ require 'providers/html_based_provider'
6
6
  require 'providers/html_based/onet_pl'
7
7
  require 'providers/html_based/interia_pl'
8
- require 'providers/html_based/wp_pl'
8
+ require 'providers/html_based/wp_pl'
9
+ require 'providers/html_based/world_weather_online'
10
+
11
+ require 'providers/metar_provider'
12
+ require 'providers/metar/noaa'
13
+ require 'providers/metar/all_met_sat'
14
+ require 'providers/metar/aviation_weather'
15
+ require 'providers/metar/wunderground'
@@ -0,0 +1,10 @@
1
+ # Daemon
2
+ module WeatherFetcher
3
+ class Server
4
+
5
+ def initialize(h = { })
6
+ @h = h
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,55 @@
1
+ class Time
2
+ # Create Time from YYYY-MM-DD HH:mm A/PM string format
3
+ #
4
+ # :call-seq:
5
+ # Time.create_time_from_string( String date, String time ) => Time
6
+ def self.create_time_from_string_12_utc(date, time)
7
+ if date.nil?
8
+ y = Time.now.year
9
+ m = Time.now.month
10
+ d = Time.now.day
11
+ else
12
+ date =~ /(\d{4})-(\d{1,2})-(\d{1,2})/
13
+ y = $1.to_i
14
+ mo = $2.to_i
15
+ d = $3.to_i
16
+ end
17
+
18
+ # hour
19
+ time =~ /(\d{1,2}):(\d{1,2}) ([PM])M/
20
+ h = $1.to_i
21
+ m = $2.to_i
22
+
23
+ if $3 == "P"
24
+ h_plus = 12
25
+ else
26
+ h_plus = 0
27
+ end
28
+ h += h_plus
29
+ h = h % 24
30
+
31
+ return Time.utc(y, mo, d, h, m).localtime
32
+
33
+ end
34
+
35
+ # Create Time from YYYY-MM-DD HH:mm string format
36
+ #
37
+ # :call-seq:
38
+ # Time.create_time_from_string( String date, String time ) => Time
39
+ def self.create_time_from_string(date, time)
40
+ date =~ /(\d{4})-(\d{1,2})-(\d{1,2})/
41
+ y = $1.to_i
42
+ m = $2.to_i
43
+ d = $3.to_i
44
+
45
+ if time =~ /(\d{1,2}):(\d{1,2})/
46
+ h = $1.to_i
47
+ min = $2.to_i
48
+ else
49
+ h = 0
50
+ min = 0
51
+ end
52
+
53
+ return Time.mktime(y, m, d, h, min, 0, 0)
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ # Fetcher
2
+ module WeatherFetcher
3
+ class WeatherData
4
+
5
+ # TODO move to other gem
6
+
7
+ def initialize(h = { })
8
+ @h = h
9
+ @h.keys.each do |k|
10
+ self.instance_variable_set("@#{k}".to_sym, @h[k])
11
+ #send :attr_accessor, k
12
+ end
13
+ end
14
+
15
+ # Return Array of WeatherData objects
16
+ def self.factory(obj)
17
+ return [ new(obj) ] if obj.kind_of? Hash
18
+ return factory_from_array(obj) if obj.kind_of? Array
19
+ end
20
+
21
+ def self.factory_from_array(array = [])
22
+ ao = Array.new
23
+ array.each do |a|
24
+ obj = self.new(a)
25
+ ao << obj
26
+ end
27
+ return ao
28
+ end
29
+
30
+ attr_reader :temperature, :wind, :time_from, :time_to
31
+
32
+ end
33
+ end
@@ -1,7 +1,12 @@
1
1
  $:.unshift(File.dirname(__FILE__))
2
2
 
3
+ require 'weather_fetcher/utils/time'
4
+
5
+ require 'weather_fetcher/weather_data'
3
6
  require 'weather_fetcher/providers'
4
7
  require 'weather_fetcher/provider_list'
8
+ require 'weather_fetcher/fetcher'
9
+ require 'weather_fetcher/server'
5
10
 
6
11
  module WeatherFetcher
7
12
  end
metadata CHANGED
@@ -1,110 +1,91 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: weather_fetcher
3
- version: !ruby/object:Gem::Version
4
- hash: 29
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
5
  prerelease:
6
- segments:
7
- - 0
8
- - 0
9
- - 1
10
- version: 0.0.1
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Aleksander Kwiatkowski
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2011-12-25 00:00:00 Z
19
- dependencies:
20
- - !ruby/object:Gem::Dependency
21
- requirement: &id001 !ruby/object:Gem::Requirement
12
+ date: 2012-03-17 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: simple_metar_parser
16
+ requirement: &26196120 !ruby/object:Gem::Requirement
22
17
  none: false
23
- requirements:
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.0.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *26196120
25
+ - !ruby/object:Gem::Dependency
26
+ name: rspec
27
+ requirement: &26195620 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
24
30
  - - ~>
25
- - !ruby/object:Gem::Version
26
- hash: 3
27
- segments:
28
- - 2
29
- - 3
30
- - 0
31
+ - !ruby/object:Gem::Version
31
32
  version: 2.3.0
32
- version_requirements: *id001
33
- name: rspec
34
- prerelease: false
35
33
  type: :development
36
- - !ruby/object:Gem::Dependency
37
- requirement: &id002 !ruby/object:Gem::Requirement
34
+ prerelease: false
35
+ version_requirements: *26195620
36
+ - !ruby/object:Gem::Dependency
37
+ name: bundler
38
+ requirement: &26195100 !ruby/object:Gem::Requirement
38
39
  none: false
39
- requirements:
40
+ requirements:
40
41
  - - ~>
41
- - !ruby/object:Gem::Version
42
- hash: 23
43
- segments:
44
- - 1
45
- - 0
46
- - 0
42
+ - !ruby/object:Gem::Version
47
43
  version: 1.0.0
48
- version_requirements: *id002
49
- name: bundler
50
- prerelease: false
51
44
  type: :development
52
- - !ruby/object:Gem::Dependency
53
- requirement: &id003 !ruby/object:Gem::Requirement
45
+ prerelease: false
46
+ version_requirements: *26195100
47
+ - !ruby/object:Gem::Dependency
48
+ name: jeweler
49
+ requirement: &26194600 !ruby/object:Gem::Requirement
54
50
  none: false
55
- requirements:
51
+ requirements:
56
52
  - - ~>
57
- - !ruby/object:Gem::Version
58
- hash: 7
59
- segments:
60
- - 1
61
- - 6
62
- - 4
53
+ - !ruby/object:Gem::Version
63
54
  version: 1.6.4
64
- version_requirements: *id003
65
- name: jeweler
66
- prerelease: false
67
55
  type: :development
68
- - !ruby/object:Gem::Dependency
69
- requirement: &id004 !ruby/object:Gem::Requirement
70
- none: false
71
- requirements:
72
- - - ">="
73
- - !ruby/object:Gem::Version
74
- hash: 3
75
- segments:
76
- - 0
77
- version: "0"
78
- version_requirements: *id004
79
- name: rcov
80
56
  prerelease: false
81
- type: :development
82
- - !ruby/object:Gem::Dependency
83
- requirement: &id005 !ruby/object:Gem::Requirement
57
+ version_requirements: *26194600
58
+ - !ruby/object:Gem::Dependency
59
+ name: simplecov
60
+ requirement: &26194080 !ruby/object:Gem::Requirement
84
61
  none: false
85
- requirements:
86
- - - ">="
87
- - !ruby/object:Gem::Version
88
- hash: 3
89
- segments:
90
- - 0
91
- version: "0"
92
- version_requirements: *id005
93
- name: rdoc
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
94
67
  prerelease: false
68
+ version_requirements: *26194080
69
+ - !ruby/object:Gem::Dependency
70
+ name: rdoc
71
+ requirement: &26193580 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
95
77
  type: :development
96
- description: Fetch weather from various Polish websites and via other gems. At the moment it is only polish portal Onet.pl but more providers will come soon.
78
+ prerelease: false
79
+ version_requirements: *26193580
80
+ description: Fetch weather from various Polish websites and via other gems. At the
81
+ moment it is only polish portal Onet.pl but more providers will come soon.
97
82
  email: bobikx@poczta.fm
98
83
  executables: []
99
-
100
84
  extensions: []
101
-
102
- extra_rdoc_files:
85
+ extra_rdoc_files:
103
86
  - LICENSE.txt
104
87
  - README.rdoc
105
- files:
106
- - .document
107
- - .rspec
88
+ files:
108
89
  - Gemfile
109
90
  - Gemfile.lock
110
91
  - LICENSE.txt
@@ -112,55 +93,49 @@ files:
112
93
  - Rakefile
113
94
  - VERSION
114
95
  - lib/weather_fetcher.rb
96
+ - lib/weather_fetcher/fetcher.rb
115
97
  - lib/weather_fetcher/provider_list.rb
116
98
  - lib/weather_fetcher/providers.rb
117
- - lib/weather_fetcher/providers/html_based.rb
118
99
  - lib/weather_fetcher/providers/html_based/interia_pl.rb
119
100
  - lib/weather_fetcher/providers/html_based/onet_pl.rb
101
+ - lib/weather_fetcher/providers/html_based/world_weather_online.rb
120
102
  - lib/weather_fetcher/providers/html_based/wp_pl.rb
103
+ - lib/weather_fetcher/providers/html_based_provider.rb
104
+ - lib/weather_fetcher/providers/metar/all_met_sat.rb
105
+ - lib/weather_fetcher/providers/metar/aviation_weather.rb
106
+ - lib/weather_fetcher/providers/metar/noaa.rb
107
+ - lib/weather_fetcher/providers/metar/wunderground.rb
108
+ - lib/weather_fetcher/providers/metar_provider.rb
121
109
  - lib/weather_fetcher/providers/provider.rb
122
- - spec/fixtures/interia_pl.yml
123
- - spec/fixtures/onet_pl.yml
124
- - spec/fixtures/weather.yml
125
- - spec/fixtures/wp_pl.yml
126
- - spec/providers/interia_pl_spec.rb
127
- - spec/providers/onet_pl_spec.rb
128
- - spec/providers/wp_pl_spec.rb
129
- - spec/spec_helper.rb
130
- - spec/weather_fetcher_spec.rb
131
- - weather_fetcher.gemspec
110
+ - lib/weather_fetcher/server.rb
111
+ - lib/weather_fetcher/utils/time.rb
112
+ - lib/weather_fetcher/weather_data.rb
132
113
  homepage: http://github.com/akwiatkowski/weather_fetcher
133
- licenses:
114
+ licenses:
134
115
  - LGPLv3
135
116
  post_install_message:
136
117
  rdoc_options: []
137
-
138
- require_paths:
118
+ require_paths:
139
119
  - lib
140
- required_ruby_version: !ruby/object:Gem::Requirement
120
+ required_ruby_version: !ruby/object:Gem::Requirement
141
121
  none: false
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- hash: 3
146
- segments:
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ segments:
147
127
  - 0
148
- version: "0"
149
- required_rubygems_version: !ruby/object:Gem::Requirement
128
+ hash: -3286165860735989117
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
150
130
  none: false
151
- requirements:
152
- - - ">="
153
- - !ruby/object:Gem::Version
154
- hash: 3
155
- segments:
156
- - 0
157
- version: "0"
131
+ requirements:
132
+ - - ! '>='
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
158
135
  requirements: []
159
-
160
136
  rubyforge_project:
161
- rubygems_version: 1.8.10
137
+ rubygems_version: 1.8.15
162
138
  signing_key:
163
139
  specification_version: 3
164
140
  summary: Fetch weather from various Polish websites and via other gems
165
141
  test_files: []
166
-
data/.document DELETED
@@ -1,5 +0,0 @@
1
- lib/**/*.rb
2
- bin/*
3
- -
4
- features/**/*.feature
5
- LICENSE.txt
data/.rspec DELETED
@@ -1 +0,0 @@
1
- --color
@@ -1,6 +0,0 @@
1
- - :url: 'http://pogoda.interia.pl/miasta?id=11721'
2
- :city: 'Inowrocław'
3
- :country: 'Poland'
4
- :coord:
5
- :lat: 52.799264
6
- :lon: 18.259935
@@ -1,6 +0,0 @@
1
- - :url: 'http://pogoda.onet.pl/0,846,38,,,inowroclaw,miasto.html'
2
- :city: 'Inowrocław'
3
- :country: 'Poland'
4
- :coord:
5
- :lat: 52.799264
6
- :lon: 18.259935
@@ -1,8 +0,0 @@
1
- - :url:
2
- Interia.pl: 'http://pogoda.interia.pl/miasta?id=11721'
3
- Onet.pl: 'http://pogoda.onet.pl/0,846,38,,,inowroclaw,miasto.html'
4
- :city: 'Inowrocław'
5
- :country: 'Poland'
6
- :coord:
7
- :lat: 52.799264
8
- :lon: 18.259935
@@ -1,6 +0,0 @@
1
- - :url: 'http://pogoda.wp.pl/miasto,bydgoszcz,mid,1201023,mi.html'
2
- :city: 'Bydgoszcz'
3
- :country: 'Poland'
4
- :coord:
5
- :lat: 53.128893
6
- :lon: 18.006363
@@ -1,14 +0,0 @@
1
- describe "WeatherFetcher::Provider::InteriaPl", :html => true do
2
- before :each do
3
- @defs = load_fixture('interia_pl')
4
- @defs.size.should > 0
5
- end
6
-
7
- it "simple fetch" do
8
- f = WeatherFetcher::Provider::InteriaPl.new(@defs)
9
- weathers = f.fetch
10
- weathers.should == f.weathers
11
-
12
- # puts weathers.to_yaml
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- describe "WeatherFetcher::Provider::OnetPl", :html => true do
2
- before :each do
3
- @defs = load_fixture('onet_pl')
4
- @defs.size.should > 0
5
- end
6
-
7
- it "simple fetch" do
8
- f = WeatherFetcher::Provider::OnetPl.new(@defs)
9
- weathers = f.fetch
10
- weathers.should == f.weathers
11
-
12
- # puts weathers.to_yaml
13
- end
14
- end
@@ -1,14 +0,0 @@
1
- describe "WeatherFetcher::Provider::WpPl", :html => true do
2
- before :each do
3
- @defs = load_fixture('wp_pl')
4
- @defs.size.should > 0
5
- end
6
-
7
- it "simple fetch" do
8
- f = WeatherFetcher::Provider::WpPl.new(@defs)
9
- weathers = f.fetch
10
- weathers.should == f.weathers
11
-
12
- # puts weathers.to_yaml
13
- end
14
- end
data/spec/spec_helper.rb DELETED
@@ -1,17 +0,0 @@
1
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
- $LOAD_PATH.unshift(File.dirname(__FILE__))
3
- require 'rspec'
4
- require 'weather_fetcher'
5
-
6
- # Requires supporting files with custom matchers and macros, etc,
7
- # in ./support/ and its subdirectories.
8
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
9
-
10
- RSpec.configure do |config|
11
- #config.filter_run :html => false
12
- #config.filter_run_excluding :html => true
13
- end
14
-
15
- def load_fixture(f)
16
- return YAML::load(File.open(File.join(Dir.pwd, 'spec', 'fixtures', "#{f}.yml")))
17
- end
@@ -1,26 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe "WeatherFetcher" do
4
- it "simple stuff" do
5
- WeatherFetcher.class.should == Module
6
- end
7
-
8
- it "should accept only Array or Hash definitions" do
9
- lambda { WeatherFetcher::Provider.new("ble") }.should raise_error
10
- lambda { WeatherFetcher::Provider.new(1) }.should raise_error
11
- lambda { WeatherFetcher::Provider.new() }.should_not raise_error
12
- lambda { WeatherFetcher::Provider.new([]) }.should_not raise_error
13
- lambda { WeatherFetcher::Provider.new({}) }.should_not raise_error
14
- end
15
-
16
- it "should return provider classes list" do
17
- providers = WeatherFetcher::ProviderList.providers
18
- providers.each do |p|
19
- p.should be_kind_of(Class)
20
-
21
- instance = p.new
22
- instance.should respond_to(:fetch)
23
- end
24
- end
25
-
26
- end
@@ -1,77 +0,0 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
5
-
6
- Gem::Specification.new do |s|
7
- s.name = "weather_fetcher"
8
- s.version = "0.0.1"
9
-
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Aleksander Kwiatkowski"]
12
- s.date = "2011-12-25"
13
- s.description = "Fetch weather from various Polish websites and via other gems. At the moment it is only polish portal Onet.pl but more providers will come soon."
14
- s.email = "bobikx@poczta.fm"
15
- s.extra_rdoc_files = [
16
- "LICENSE.txt",
17
- "README.rdoc"
18
- ]
19
- s.files = [
20
- ".document",
21
- ".rspec",
22
- "Gemfile",
23
- "Gemfile.lock",
24
- "LICENSE.txt",
25
- "README.rdoc",
26
- "Rakefile",
27
- "VERSION",
28
- "lib/weather_fetcher.rb",
29
- "lib/weather_fetcher/provider_list.rb",
30
- "lib/weather_fetcher/providers.rb",
31
- "lib/weather_fetcher/providers/html_based.rb",
32
- "lib/weather_fetcher/providers/html_based/interia_pl.rb",
33
- "lib/weather_fetcher/providers/html_based/onet_pl.rb",
34
- "lib/weather_fetcher/providers/html_based/wp_pl.rb",
35
- "lib/weather_fetcher/providers/provider.rb",
36
- "spec/fixtures/interia_pl.yml",
37
- "spec/fixtures/onet_pl.yml",
38
- "spec/fixtures/weather.yml",
39
- "spec/fixtures/wp_pl.yml",
40
- "spec/providers/interia_pl_spec.rb",
41
- "spec/providers/onet_pl_spec.rb",
42
- "spec/providers/wp_pl_spec.rb",
43
- "spec/spec_helper.rb",
44
- "spec/weather_fetcher_spec.rb",
45
- "weather_fetcher.gemspec"
46
- ]
47
- s.homepage = "http://github.com/akwiatkowski/weather_fetcher"
48
- s.licenses = ["LGPLv3"]
49
- s.require_paths = ["lib"]
50
- s.rubygems_version = "1.8.10"
51
- s.summary = "Fetch weather from various Polish websites and via other gems"
52
-
53
- if s.respond_to? :specification_version then
54
- s.specification_version = 3
55
-
56
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
- s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
58
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
59
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
60
- s.add_development_dependency(%q<rcov>, [">= 0"])
61
- s.add_development_dependency(%q<rdoc>, [">= 0"])
62
- else
63
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
64
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
65
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
66
- s.add_dependency(%q<rcov>, [">= 0"])
67
- s.add_dependency(%q<rdoc>, [">= 0"])
68
- end
69
- else
70
- s.add_dependency(%q<rspec>, ["~> 2.3.0"])
71
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
72
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
73
- s.add_dependency(%q<rcov>, [">= 0"])
74
- s.add_dependency(%q<rdoc>, [">= 0"])
75
- end
76
- end
77
-