weather_fetcher 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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
-