barometer 0.8.0 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (321) hide show
  1. data/.gitignore +2 -0
  2. data/.pelusa.yml +7 -0
  3. data/.travis.yml +6 -3
  4. data/Gemfile +11 -1
  5. data/README.md +89 -244
  6. data/Rakefile +1 -1
  7. data/barometer.gemspec +22 -24
  8. data/lib/barometer.rb +14 -65
  9. data/lib/barometer/base.rb +35 -65
  10. data/lib/barometer/data.rb +15 -20
  11. data/lib/barometer/data/attribute.rb +19 -0
  12. data/lib/barometer/data/attributes/distance.rb +11 -0
  13. data/lib/barometer/data/attributes/float.rb +11 -0
  14. data/lib/barometer/data/attributes/integer.rb +11 -0
  15. data/lib/barometer/data/attributes/location.rb +11 -0
  16. data/lib/barometer/data/attributes/pressure.rb +11 -0
  17. data/lib/barometer/data/attributes/sun.rb +15 -0
  18. data/lib/barometer/data/attributes/temperature.rb +11 -0
  19. data/lib/barometer/data/attributes/time.rb +11 -0
  20. data/lib/barometer/data/attributes/vector.rb +11 -0
  21. data/lib/barometer/data/attributes/zone.rb +11 -0
  22. data/lib/barometer/data/convertable_units.rb +145 -0
  23. data/lib/barometer/data/coordinates.rb +16 -0
  24. data/lib/barometer/data/distance.rb +14 -133
  25. data/lib/barometer/data/geo.rb +22 -59
  26. data/lib/barometer/data/location.rb +14 -20
  27. data/lib/barometer/data/pressure.rb +14 -135
  28. data/lib/barometer/data/sun.rb +24 -24
  29. data/lib/barometer/data/temperature.rb +14 -169
  30. data/lib/barometer/data/vector.rb +44 -0
  31. data/lib/barometer/data/zone.rb +109 -112
  32. data/lib/barometer/query.rb +23 -161
  33. data/lib/barometer/query/base.rb +88 -0
  34. data/lib/barometer/query/converter.rb +64 -0
  35. data/lib/barometer/query/converters/from_coordinates_to_noaa_station_id.rb +30 -0
  36. data/lib/barometer/query/converters/from_geocode_to_coordinates.rb +28 -0
  37. data/lib/barometer/query/converters/from_short_zipcode_to_zipcode.rb +28 -0
  38. data/lib/barometer/query/converters/from_weather_id_to_geocode.rb +30 -0
  39. data/lib/barometer/query/converters/from_woe_id_or_ipv4_to_geocode.rb +32 -0
  40. data/lib/barometer/query/converters/to_geocode.rb +30 -0
  41. data/lib/barometer/query/converters/to_weather_id.rb +30 -0
  42. data/lib/barometer/query/converters/to_woe_id.rb +30 -0
  43. data/lib/barometer/query/format.rb +59 -0
  44. data/lib/barometer/query/formats/base.rb +22 -0
  45. data/lib/barometer/query/formats/coordinates.rb +14 -0
  46. data/lib/barometer/query/formats/geocode.rb +15 -0
  47. data/lib/barometer/query/formats/icao.rb +35 -0
  48. data/lib/barometer/query/formats/ipv4_address.rb +19 -0
  49. data/lib/barometer/query/formats/noaa_station_id.rb +15 -0
  50. data/lib/barometer/query/formats/postalcode.rb +20 -0
  51. data/lib/barometer/query/formats/short_zipcode.rb +15 -0
  52. data/lib/barometer/{translations → query/formats/translations}/icao_country_codes.yml +0 -0
  53. data/lib/barometer/{translations → query/formats/translations}/weather_country_codes.yml +0 -0
  54. data/lib/barometer/query/formats/unknown.rb +14 -0
  55. data/lib/barometer/query/formats/weather_id.rb +33 -0
  56. data/lib/barometer/query/formats/woe_id.rb +28 -0
  57. data/lib/barometer/query/formats/zipcode.rb +15 -0
  58. data/lib/barometer/query/service.rb +13 -0
  59. data/lib/barometer/query/services/apis/geonames_timezone.rb +26 -0
  60. data/lib/barometer/query/services/apis/google_geocode.rb +35 -0
  61. data/lib/barometer/query/services/apis/noaa_station.rb +31 -0
  62. data/lib/barometer/query/services/apis/weather_id.rb +35 -0
  63. data/lib/barometer/query/services/apis/wunderground_timezone.rb +26 -0
  64. data/lib/barometer/query/services/apis/yahoo_placefinder.rb +35 -0
  65. data/lib/barometer/query/services/apis/yahoo_weather.rb +31 -0
  66. data/lib/barometer/query/services/from_weather_id.rb +64 -0
  67. data/lib/barometer/query/services/geonames_timezone.rb +18 -0
  68. data/lib/barometer/query/services/google_geocode.rb +106 -0
  69. data/lib/barometer/query/services/noaa_station_id.rb +28 -0
  70. data/lib/barometer/query/services/to_weather_id.rb +25 -0
  71. data/lib/barometer/query/services/to_woe_id.rb +29 -0
  72. data/lib/barometer/query/services/wunderground_timezone.rb +18 -0
  73. data/lib/barometer/query/services/yahoo_geocode.rb +69 -0
  74. data/lib/barometer/response.rb +12 -0
  75. data/lib/barometer/response/base.rb +57 -0
  76. data/lib/barometer/response/current.rb +27 -0
  77. data/lib/barometer/response/prediction.rb +41 -0
  78. data/lib/barometer/response/prediction_collection.rb +48 -0
  79. data/lib/barometer/utils.rb +17 -0
  80. data/lib/barometer/utils/address.rb +33 -0
  81. data/lib/barometer/utils/api.rb +30 -0
  82. data/lib/barometer/utils/config_reader.rb +40 -0
  83. data/lib/barometer/utils/get.rb +17 -0
  84. data/lib/barometer/utils/json_reader.rb +22 -0
  85. data/lib/barometer/utils/payload.rb +100 -0
  86. data/lib/barometer/utils/payload_request.rb +37 -0
  87. data/lib/barometer/utils/post.rb +24 -0
  88. data/lib/barometer/utils/time.rb +78 -0
  89. data/lib/barometer/{translations → utils/translations}/zone_codes.yml +0 -0
  90. data/lib/barometer/utils/versioned_registration.rb +70 -0
  91. data/lib/barometer/utils/xml_reader.rb +27 -0
  92. data/lib/barometer/utils/zone_code_lookup.rb +30 -0
  93. data/lib/barometer/version.rb +1 -1
  94. data/lib/barometer/weather.rb +44 -173
  95. data/lib/barometer/weather_service.rb +41 -0
  96. data/lib/barometer/weather_services/base.rb +50 -0
  97. data/lib/barometer/weather_services/forecast_io.rb +36 -0
  98. data/lib/barometer/weather_services/forecast_io/api.rb +22 -0
  99. data/lib/barometer/weather_services/forecast_io/query.rb +38 -0
  100. data/lib/barometer/weather_services/forecast_io/response.rb +31 -0
  101. data/lib/barometer/weather_services/forecast_io/response/current_weather.rb +78 -0
  102. data/lib/barometer/weather_services/forecast_io/response/forecasted_weather.rb +74 -0
  103. data/lib/barometer/weather_services/forecast_io/response/location.rb +19 -0
  104. data/lib/barometer/weather_services/forecast_io/response/timezone.rb +25 -0
  105. data/lib/barometer/weather_services/noaa.rb +21 -305
  106. data/lib/barometer/weather_services/noaa/current_api.rb +25 -0
  107. data/lib/barometer/weather_services/noaa/current_query.rb +30 -0
  108. data/lib/barometer/weather_services/noaa/current_response.rb +29 -0
  109. data/lib/barometer/weather_services/noaa/forecast_api.rb +25 -0
  110. data/lib/barometer/weather_services/noaa/forecast_query.rb +39 -0
  111. data/lib/barometer/weather_services/noaa/forecast_response.rb +28 -0
  112. data/lib/barometer/weather_services/noaa/response/current_location.rb +42 -0
  113. data/lib/barometer/weather_services/noaa/response/current_station.rb +46 -0
  114. data/lib/barometer/weather_services/noaa/response/current_weather.rb +82 -0
  115. data/lib/barometer/weather_services/noaa/response/forecasted_weather.rb +90 -0
  116. data/lib/barometer/weather_services/noaa/response/location.rb +19 -0
  117. data/lib/barometer/weather_services/noaa/response/timezone.rb +15 -0
  118. data/lib/barometer/weather_services/response.rb +9 -0
  119. data/lib/barometer/weather_services/response/location.rb +42 -0
  120. data/lib/barometer/weather_services/response/time_zone.rb +19 -0
  121. data/lib/barometer/weather_services/weather_bug.rb +24 -280
  122. data/lib/barometer/weather_services/weather_bug/current_api.rb +26 -0
  123. data/lib/barometer/weather_services/weather_bug/current_response.rb +33 -0
  124. data/lib/barometer/weather_services/weather_bug/forecast_api.rb +26 -0
  125. data/lib/barometer/weather_services/weather_bug/forecast_response.rb +29 -0
  126. data/lib/barometer/weather_services/weather_bug/query.rb +42 -0
  127. data/lib/barometer/weather_services/weather_bug/response/current_weather.rb +82 -0
  128. data/lib/barometer/weather_services/weather_bug/response/forecasted_weather.rb +67 -0
  129. data/lib/barometer/weather_services/weather_bug/response/location.rb +23 -0
  130. data/lib/barometer/weather_services/weather_bug/response/station.rb +43 -0
  131. data/lib/barometer/weather_services/weather_bug/response/sun.rb +32 -0
  132. data/lib/barometer/weather_services/weather_bug/response/time_helper.rb +52 -0
  133. data/lib/barometer/weather_services/weather_bug/response/timezone.rb +15 -0
  134. data/lib/barometer/weather_services/wunderground_v1.rb +32 -0
  135. data/lib/barometer/weather_services/wunderground_v1/current_api.rb +21 -0
  136. data/lib/barometer/weather_services/wunderground_v1/current_response.rb +31 -0
  137. data/lib/barometer/weather_services/wunderground_v1/forecast_api.rb +21 -0
  138. data/lib/barometer/weather_services/wunderground_v1/forecast_response.rb +33 -0
  139. data/lib/barometer/weather_services/wunderground_v1/query.rb +30 -0
  140. data/lib/barometer/weather_services/wunderground_v1/response/current_weather.rb +92 -0
  141. data/lib/barometer/weather_services/wunderground_v1/response/forecasted_weather.rb +87 -0
  142. data/lib/barometer/weather_services/wunderground_v1/response/full_timezone.rb +22 -0
  143. data/lib/barometer/weather_services/wunderground_v1/response/location.rb +43 -0
  144. data/lib/barometer/weather_services/wunderground_v1/response/station.rb +39 -0
  145. data/lib/barometer/weather_services/wunderground_v1/response/sun.rb +53 -0
  146. data/lib/barometer/weather_services/wunderground_v1/response/timezone.rb +15 -0
  147. data/lib/barometer/weather_services/yahoo.rb +16 -198
  148. data/lib/barometer/weather_services/yahoo/api.rb +21 -0
  149. data/lib/barometer/weather_services/yahoo/query.rb +42 -0
  150. data/lib/barometer/weather_services/yahoo/response.rb +39 -0
  151. data/lib/barometer/weather_services/yahoo/response/current_weather.rb +86 -0
  152. data/lib/barometer/weather_services/yahoo/response/forecasted_weather.rb +71 -0
  153. data/lib/barometer/weather_services/yahoo/response/location.rb +47 -0
  154. data/lib/barometer/weather_services/yahoo/response/sun.rb +43 -0
  155. data/lib/barometer/weather_services/yahoo/response/timezone.rb +15 -0
  156. data/spec/barometer_spec.rb +18 -120
  157. data/spec/base_spec.rb +114 -0
  158. data/spec/cassettes/Converter_FromCoordinatesToNoaaStationId.json +1 -0
  159. data/spec/cassettes/Converter_FromWeatherIdToGeocode.json +1 -0
  160. data/spec/cassettes/Converter_FromWoeIdOrIpv4ToGeocode.json +1 -0
  161. data/spec/cassettes/Converter_ToGeocode.json +1 -0
  162. data/spec/cassettes/Converter_ToWeatherId.json +1 -0
  163. data/spec/cassettes/Converter_ToWoeId.json +1 -0
  164. data/spec/cassettes/Service_FromWeatherId.json +1 -0
  165. data/spec/cassettes/Service_GoogleGeocode.json +1 -0
  166. data/spec/cassettes/Service_NoaaStation.json +1 -0
  167. data/spec/cassettes/Service_ToWeatherId.json +1 -0
  168. data/spec/cassettes/Service_ToWoeId.json +1 -0
  169. data/spec/cassettes/Service_YahooGeocode.json +1 -0
  170. data/spec/cassettes/WeatherService_ForecastIo.json +1 -0
  171. data/spec/cassettes/WeatherService_Noaa.json +1 -1
  172. data/spec/cassettes/WeatherService_WeatherBug.json +1 -1
  173. data/spec/cassettes/WeatherService_WundergroundV1.json +1 -0
  174. data/spec/cassettes/WeatherService_Yahoo.json +1 -1
  175. data/spec/data/attributes/distance_spec.rb +60 -0
  176. data/spec/data/attributes/location_spec.rb +41 -0
  177. data/spec/data/attributes/pressure_spec.rb +60 -0
  178. data/spec/data/attributes/sun_spec.rb +33 -0
  179. data/spec/data/attributes/temperature_spec.rb +60 -0
  180. data/spec/data/attributes/time_spec.rb +58 -0
  181. data/spec/data/attributes/vector_spec.rb +43 -0
  182. data/spec/data/attributes/zone_spec.rb +34 -0
  183. data/spec/data/convertable_units_spec.rb +299 -0
  184. data/spec/data/coordinates_spec.rb +15 -0
  185. data/spec/data/distance_spec.rb +49 -333
  186. data/spec/data/geo_spec.rb +72 -71
  187. data/spec/data/location_spec.rb +70 -65
  188. data/spec/data/pressure_spec.rb +49 -333
  189. data/spec/data/sun_spec.rb +57 -81
  190. data/spec/data/temperature_spec.rb +49 -393
  191. data/spec/data/vector_spec.rb +100 -0
  192. data/spec/data/zone_spec.rb +199 -266
  193. data/spec/query/base_spec.rb +296 -0
  194. data/spec/query/converter_spec.rb +98 -0
  195. data/spec/query/converters/from_coordinates_to_noaa_station_id_spec.rb +35 -0
  196. data/spec/query/converters/from_geocode_to_coordinates_spec.rb +25 -0
  197. data/spec/query/converters/from_short_zipcode_to_zipcode_spec.rb +31 -0
  198. data/spec/query/converters/from_weather_id_to_geocode_spec.rb +40 -0
  199. data/spec/query/converters/from_woe_id_or_ipv4_to_geocode_spec.rb +51 -0
  200. data/spec/query/converters/to_geocode_spec.rb +99 -0
  201. data/spec/query/converters/to_weather_id_spec.rb +35 -0
  202. data/spec/query/converters/to_woe_id_spec.rb +74 -0
  203. data/spec/query/formats/base_spec.rb +15 -0
  204. data/spec/query/formats/coordinates_spec.rb +13 -0
  205. data/spec/query/formats/geocode_spec.rb +9 -0
  206. data/spec/query/formats/icao_spec.rb +20 -0
  207. data/spec/query/formats/ipv4_address_spec.rb +33 -0
  208. data/spec/query/formats/noaa_station_id_spec.rb +9 -0
  209. data/spec/query/formats/postalcode_spec.rb +18 -0
  210. data/spec/query/formats/short_zipcode_spec.rb +18 -0
  211. data/spec/query/formats/unknown_spec.rb +9 -0
  212. data/spec/query/formats/weather_id_spec.rb +31 -0
  213. data/spec/query/formats/woe_id_spec.rb +45 -0
  214. data/spec/query/formats/zipcode_spec.rb +18 -0
  215. data/spec/query/formats_spec.rb +55 -0
  216. data/spec/query/services/from_weather_id_spec.rb +54 -0
  217. data/spec/query/services/google_geocode_spec.rb +60 -0
  218. data/spec/query/services/noaa_station_id_spec.rb +23 -0
  219. data/spec/query/services/to_weather_id_spec.rb +23 -0
  220. data/spec/query/services/to_woe_id_spec.rb +51 -0
  221. data/spec/query/services/yahoo_geocode_spec.rb +72 -0
  222. data/spec/response/base_spec.rb +103 -0
  223. data/spec/response/current_spec.rb +33 -0
  224. data/spec/response/predicition_spec.rb +65 -0
  225. data/spec/response/prediction_collection_spec.rb +97 -0
  226. data/spec/spec_helper.rb +14 -12
  227. data/spec/support/key_file_parser.rb +22 -0
  228. data/spec/support/matchers/formats.rb +36 -0
  229. data/spec/support/matchers/have_data.rb +46 -0
  230. data/spec/support/matchers/have_field.rb +128 -0
  231. data/spec/support/matchers/have_forecast.rb +46 -0
  232. data/spec/support/matchers/path.rb +23 -0
  233. data/spec/support/query_factory.rb +20 -0
  234. data/spec/utils/address_spec.rb +67 -0
  235. data/spec/utils/config_reader_spec.rb +157 -0
  236. data/spec/utils/get_spec.rb +22 -0
  237. data/spec/utils/payload_request_spec.rb +69 -0
  238. data/spec/utils/payload_spec.rb +168 -0
  239. data/spec/utils/post_spec.rb +20 -0
  240. data/spec/utils/time_spec.rb +93 -0
  241. data/spec/utils/versioned_registration_spec.rb +105 -0
  242. data/spec/weather_services/base_spec.rb +116 -0
  243. data/spec/weather_services/forecast_io_spec.rb +71 -0
  244. data/spec/weather_services/noaa/current_response_spec.rb +22 -0
  245. data/spec/weather_services/noaa/forecast_response_spec.rb +33 -0
  246. data/spec/weather_services/noaa_spec.rb +68 -166
  247. data/spec/weather_services/weather_bug/current_response_spec.rb +64 -0
  248. data/spec/weather_services/weather_bug/forecast_response_spec.rb +23 -0
  249. data/spec/weather_services/weather_bug_spec.rb +62 -202
  250. data/spec/weather_services/wunderground_v1/current_response_spec.rb +19 -0
  251. data/spec/weather_services/wunderground_v1/forecast_response_spec.rb +62 -0
  252. data/spec/weather_services/wunderground_v1_spec.rb +78 -0
  253. data/spec/weather_services/yahoo/response_spec.rb +73 -0
  254. data/spec/weather_services/yahoo_spec.rb +52 -135
  255. data/spec/weather_services_spec.rb +103 -0
  256. data/spec/weather_spec.rb +167 -347
  257. metadata +342 -123
  258. data/.document +0 -5
  259. data/TODO +0 -60
  260. data/bin/barometer +0 -441
  261. data/lib/barometer/data/local_datetime.rb +0 -145
  262. data/lib/barometer/data/local_time.rb +0 -134
  263. data/lib/barometer/data/speed.rb +0 -158
  264. data/lib/barometer/data/units.rb +0 -49
  265. data/lib/barometer/formats.rb +0 -13
  266. data/lib/barometer/formats/coordinates.rb +0 -57
  267. data/lib/barometer/formats/format.rb +0 -64
  268. data/lib/barometer/formats/geocode.rb +0 -60
  269. data/lib/barometer/formats/icao.rb +0 -37
  270. data/lib/barometer/formats/postalcode.rb +0 -22
  271. data/lib/barometer/formats/short_zipcode.rb +0 -17
  272. data/lib/barometer/formats/weather_id.rb +0 -92
  273. data/lib/barometer/formats/woe_id.rb +0 -150
  274. data/lib/barometer/formats/zipcode.rb +0 -31
  275. data/lib/barometer/key_file_parser.rb +0 -20
  276. data/lib/barometer/measurements/measurement.rb +0 -202
  277. data/lib/barometer/measurements/result.rb +0 -207
  278. data/lib/barometer/measurements/result_array.rb +0 -75
  279. data/lib/barometer/services.rb +0 -19
  280. data/lib/barometer/weather_services/service.rb +0 -189
  281. data/lib/barometer/weather_services/wunderground.rb +0 -264
  282. data/lib/barometer/web_services/geocode.rb +0 -34
  283. data/lib/barometer/web_services/noaa_station_id.rb +0 -53
  284. data/lib/barometer/web_services/placemaker.rb +0 -95
  285. data/lib/barometer/web_services/timezone.rb +0 -38
  286. data/lib/barometer/web_services/weather_id.rb +0 -50
  287. data/lib/barometer/web_services/web_service.rb +0 -29
  288. data/spec/cassettes/Barometer.json +0 -1
  289. data/spec/cassettes/Query.json +0 -1
  290. data/spec/cassettes/Query_Format_Coordinates.json +0 -1
  291. data/spec/cassettes/Query_Format_Geocode.json +0 -1
  292. data/spec/cassettes/Query_Format_WeatherID.json +0 -1
  293. data/spec/cassettes/Query_Format_WoeID.json +0 -1
  294. data/spec/cassettes/WeatherService.json +0 -1
  295. data/spec/cassettes/WeatherService_Wunderground.json +0 -1
  296. data/spec/cassettes/WebService_Geocode.json +0 -1
  297. data/spec/cassettes/WebService_NoaaStation.json +0 -1
  298. data/spec/data/local_datetime_spec.rb +0 -274
  299. data/spec/data/local_time_spec.rb +0 -239
  300. data/spec/data/speed_spec.rb +0 -374
  301. data/spec/data/units_spec.rb +0 -101
  302. data/spec/formats/coordinates_spec.rb +0 -166
  303. data/spec/formats/format_spec.rb +0 -74
  304. data/spec/formats/geocode_spec.rb +0 -163
  305. data/spec/formats/icao_spec.rb +0 -55
  306. data/spec/formats/postalcode_spec.rb +0 -53
  307. data/spec/formats/short_zipcode_spec.rb +0 -47
  308. data/spec/formats/weather_id_spec.rb +0 -182
  309. data/spec/formats/woe_id_spec.rb +0 -211
  310. data/spec/formats/zipcode_spec.rb +0 -103
  311. data/spec/key_file_parser_spec.rb +0 -28
  312. data/spec/measurements/measurement_spec.rb +0 -381
  313. data/spec/measurements/result_array_spec.rb +0 -150
  314. data/spec/measurements/result_spec.rb +0 -632
  315. data/spec/query_spec.rb +0 -498
  316. data/spec/weather_services/services_spec.rb +0 -135
  317. data/spec/weather_services/wunderground_spec.rb +0 -179
  318. data/spec/web_services/geocode_spec.rb +0 -31
  319. data/spec/web_services/noaa_station_id_spec.rb +0 -33
  320. data/spec/web_services/placemaker_spec.rb +0 -41
  321. data/spec/web_services/web_services_spec.rb +0 -20
@@ -1,75 +0,0 @@
1
- require 'date'
2
- module Barometer
3
- #
4
- # Result Array
5
- #
6
- # an array that holds multiple results,
7
- # with methods for insertion and searching
8
- #
9
- class Measurement::ResultArray < Array
10
-
11
- def <<(forecast)
12
- raise ArgumentError unless forecast.is_a?(Measurement::Result)
13
- super(forecast)
14
- end
15
-
16
- def [](index)
17
- index.is_a?(Fixnum) ? super(index) : self.for(index)
18
- end
19
-
20
- #
21
- # Returns a forecast for a day given by a Date, DateTime,
22
- # Time, or a string that can be parsed to a Data::LocalDateTime
23
- #
24
- # credit: http://github.com/jdpace/weatherman/
25
- #
26
- def for(datetime)
27
-
28
- return nil unless self.size > 0
29
-
30
- # Format date into a Date class
31
- datetime = case datetime.class.name
32
- when 'Date'
33
- # if just given a date, assume a time that will be mid-day
34
- Data::LocalDateTime.new(datetime.year,datetime.month,datetime.day,12,0,0)
35
- when 'Data::LocalDateTime'
36
- datetime
37
- when 'String'
38
- Data::LocalDateTime.parse(datetime)
39
- when 'Time'
40
- Data::LocalDateTime.parse(datetime)
41
- when 'DateTime'
42
- Data::LocalDateTime.parse(datetime)
43
- end
44
-
45
- day = nil
46
- self.each do |f|
47
- day = f if f.for_datetime?(datetime)
48
- end
49
- return day
50
- end
51
-
52
- #
53
- # answer simple questions
54
- #
55
-
56
- def windy?(datetime, threshold=10)
57
- (forecast = self[datetime]) ? forecast.windy?(threshold) : nil
58
- end
59
-
60
- def day?(datetime)
61
- local_time = Data::LocalTime.parse(datetime)
62
- (forecast = self[datetime]) ? forecast.day?(local_time) : nil
63
- end
64
-
65
- def sunny?(datetime, sunny_icons=nil)
66
- local_time = Data::LocalTime.parse(datetime)
67
- (forecast = self[datetime]) ? forecast.sunny?(local_time, sunny_icons) : nil
68
- end
69
-
70
- def wet?(datetime, wet_icons=nil, pop_threshold=50, humidity_threshold=99)
71
- (forecast = self[datetime]) ? forecast.wet?(wet_icons,pop_threshold,humidity_threshold) : nil
72
- end
73
-
74
- end
75
- end
@@ -1,19 +0,0 @@
1
- $:.unshift(File.dirname(__FILE__))
2
-
3
- # weather services
4
- #
5
- require 'weather_services/service'
6
- require 'weather_services/wunderground'
7
- require 'weather_services/yahoo'
8
- require 'weather_services/weather_bug'
9
- require 'weather_services/noaa'
10
-
11
- #
12
- # web services (non weather)
13
- #
14
- require 'web_services/web_service'
15
- require 'web_services/geocode'
16
- require 'web_services/weather_id'
17
- require 'web_services/timezone'
18
- require 'web_services/placemaker'
19
- require 'web_services/noaa_station_id'
@@ -1,189 +0,0 @@
1
- require 'rubygems'
2
- require 'httparty'
3
-
4
- module Barometer
5
- #
6
- # Service Class
7
- #
8
- # This is a base class for creating alternate weather api-consuming
9
- # drivers. Each driver inherits from this class. This class creates
10
- # some default behaviours, but they can easily be over-ridden.
11
- #
12
- # Basically, all a service is required to do is take a query
13
- # (ie "Paris") and return a complete Barometer::Measurement instance.
14
- #
15
- class WeatherService
16
- # all service drivers will use the HTTParty gem
17
- include HTTParty
18
-
19
- # retrieves the weather source Service object
20
- def self.source(source_name)
21
- raise ArgumentError unless (source_name.is_a?(String) || source_name.is_a?(Symbol))
22
- source_name = source_name.to_s.split("_").collect{ |s| s.capitalize }.join('')
23
- raise ArgumentError unless Barometer::WeatherService.const_defined?(source_name)
24
- raise ArgumentError unless Barometer::WeatherService.const_get(source_name).superclass == Barometer::WeatherService
25
- Barometer::WeatherService.const_get(source_name)
26
- end
27
-
28
- #
29
- # get current weather and future (forecasted) weather
30
- #
31
- def self.measure(query, metric=true)
32
- raise ArgumentError unless query.is_a?(Barometer::Query)
33
-
34
- measurement = Barometer::Measurement.new(self._source_name, metric)
35
- measurement.start_at = Time.now.utc
36
-
37
- converted_query = query.convert!(self._accepted_formats)
38
- if converted_query
39
- measurement.source = self._source_name
40
- measurement.query = converted_query.q
41
- measurement.format = converted_query.format
42
- measurement = self._measure(measurement, converted_query, metric)
43
- end
44
-
45
- measurement.end_at = Time.now.utc
46
- measurement
47
- end
48
-
49
- #########################################################################
50
- # PRIVATE
51
- # If class methods could be private, the remaining methods would be.
52
- #
53
-
54
- #
55
- # REQUIRED
56
- # re-defining these methods will be required
57
- #
58
-
59
- def self._source_name; raise NotImplementedError; end
60
- def self._accepted_formats; raise NotImplementedError; end
61
- def self._fetch(query=nil, metric=true); nil; end
62
- def self._build_current(result=nil, metric=true); nil; end
63
- def self._build_forecast(result=nil, metric=true); nil; end
64
-
65
- #
66
- # PROBABLE
67
- # re-defining these methods is probable though not a must
68
- #
69
-
70
- # data processing stubs
71
- #
72
- def self._build_location(result=nil, geo=nil); nil; end
73
- def self._build_station(result=nil); Data::Location.new; end
74
- def self._build_links(result=nil); {}; end
75
- def self._build_sun(result=nil); Data::Sun.new; end
76
- def self._build_timezone(result=nil); nil; end
77
- def self._build_extra(measurement=nil, result=nil, metric=true); measurement; end
78
- def self._build_local_time(measurement)
79
- (measurement && measurement.timezone) ? Data::LocalTime.parse(measurement.timezone.now) : nil
80
- end
81
-
82
- # given the result set, return the full_timezone or local time ...
83
- # if not available return nil
84
- def self._parse_full_timezone(result=nil); nil; end
85
- def self._parse_local_time(result=nil); nil; end
86
-
87
- # this returns an array of codes that indicate "wet"
88
- def self._wet_icon_codes; nil; end
89
- # this returns an array of codes that indicate "sunny"
90
- def self._sunny_icon_codes; nil; end
91
-
92
- #
93
- # OPTIONAL
94
- # re-defining these methods will be optional
95
- #
96
-
97
- # STUB: define this method to check for the existance of API keys,
98
- # this method is NOT needed if requires_keys? returns false
99
- def self._has_keys?; raise NotImplementedError; end
100
-
101
- # STUB: define this method to check for the existance of API keys,
102
- # this method is NOT needed if requires_keys? returns false
103
- def self._keys=(keys=nil); nil; end
104
-
105
- # DEFAULT: override this if you need to determine if the country is specified
106
- def self._supports_country?(query=nil); true; end
107
-
108
- # DEFAULT: override this if you need to determine if API keys are required
109
- def self._requires_keys?; false; end
110
-
111
- # data accessors
112
- # (see the wunderground driver for an example of overriding these)
113
- #
114
- def self._current_result(data=nil); data; end
115
- def self._forecast_result(data=nil); data; end
116
- def self._location_result(data=nil); data; end
117
- def self._station_result(data=nil); data; end
118
- def self._links_result(data=nil); data; end
119
- def self._sun_result(data=nil); data; end
120
- def self._timezone_result(data=nil); data; end
121
- def self._time_result(data=nil); data; end
122
-
123
- #
124
- # COMPLETE
125
- # re-defining these methods should not be needed, as the behavior
126
- # can be adjusted using methods above
127
- #
128
-
129
- # this is the generic measuring and data processing for each weather service
130
- # driver. this method should be re-defined if the driver in question
131
- # doesn't fit into "generic" (ie wunderground)
132
- #
133
- def self._measure(measurement, query, metric=true)
134
- raise ArgumentError unless measurement.is_a?(Barometer::Measurement)
135
- raise ArgumentError unless query.is_a?(Barometer::Query)
136
-
137
- return measurement unless self._meets_requirements?(query)
138
-
139
- begin
140
- result = _fetch(query, metric)
141
- rescue Timeout::Error => e
142
- return measurement
143
- end
144
-
145
- if result
146
- measurement.current = _build_current(_current_result(result), metric)
147
- measurement.forecast = _build_forecast(_forecast_result(result), metric)
148
- measurement.location = _build_location(_location_result(result), query.geo)
149
- measurement.station = _build_station(_station_result(result))
150
- measurement.links = _build_links(_links_result(result))
151
- measurement.current.sun = _build_sun(_sun_result(result)) if measurement.current
152
- measurement.timezone = _timezone(_timezone_result(result), query, measurement.location)
153
- if local_time = _local_time(_time_result(result), measurement)
154
- measurement.measured_at = local_time
155
- measurement.current.current_at = local_time
156
- end
157
- measurement = _build_extra(measurement, result, metric)
158
- end
159
-
160
- measurement
161
- end
162
-
163
- # either get the timezone based on coords, or build it from the data
164
- #
165
- def self._timezone(result=nil, query=nil, location=nil)
166
- if full_timezone = _parse_full_timezone(result)
167
- full_timezone
168
- elsif query && query.timezone
169
- query.timezone
170
- elsif Barometer.enhance_timezone && location &&
171
- location.latitude && location.longitude
172
- WebService::Timezone.fetch(location.latitude, location.longitude)
173
- else
174
- _build_timezone(result)
175
- end
176
- end
177
-
178
- # return the current local time (as Data::LocalTime)
179
- #
180
- def self._local_time(result, measurement=nil)
181
- _parse_local_time(result) || _build_local_time(measurement)
182
- end
183
-
184
- def self._meets_requirements?(query=nil)
185
- self._supports_country?(query) && (!self._requires_keys? || self._has_keys?)
186
- end
187
-
188
- end
189
- end
@@ -1,264 +0,0 @@
1
- module Barometer
2
- #
3
- # [DEFAULT PROVIDER]
4
- #
5
- # = Weather Underground
6
- # www.wunderground.com
7
- #
8
- # - key required: NO
9
- # - registration required: NO
10
- # - supported countries: ALL
11
- #
12
- # === performs geo coding
13
- # - city: YES
14
- # - coordinates: YES
15
- # NOTE: provides geo data for location and weather station
16
- #
17
- # === time info
18
- # - sun rise/set: YES (today only)
19
- # - provides timezone: YES
20
- # - requires TZInfo: YES
21
- # *NOTE: If accuarcy of times and converting, this service is the top choice.
22
- # They provide the full timezone name that is needed for the most
23
- # accurate time conversions.
24
- #
25
- # == resources
26
- # - API: http://wiki.wunderground.com/index.php/API_-_XML
27
- #
28
- # === Possible queries:
29
- # - http://api.wunderground.com/auto/wui/geo/GeoLookupXML/index.xml?query=94107
30
- # - http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml?query=KSFO
31
- # - http://api.wunderground.com/weatherstation/WXCurrentObXML.asp?ID=KCASANFR70
32
- # - http://api.wunderground.com/auto/wui/geo/AlertsXML/index.xml?query=86445
33
- # - http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml?query=Chicago,IL
34
- #
35
- # where query can be:
36
- # - zipcode (US or Canadian)
37
- # - city state; city, state
38
- # - city
39
- # - state
40
- # - country
41
- # - airport code (3-letter or 4-letter)
42
- # - lat,lon
43
- #
44
- # = Wunderground terms of use
45
- # Unable to locate.
46
- #
47
- class WeatherService::Wunderground < WeatherService
48
-
49
- #########################################################################
50
- # PRIVATE
51
- # If class methods could be private, the remaining methods would be.
52
- #
53
-
54
- def self._source_name; :wunderground; end
55
- def self._accepted_formats
56
- [:zipcode, :postalcode, :icao, :coordinates, :geocode]
57
- end
58
-
59
- # these are the icon codes that indicate "wet", used by wet? function
60
- def self._wet_icon_codes
61
- %w(flurries rain sleet snow tstorms nt_flurries nt_rain nt_sleet nt_snow nt_tstorms chancerain chancetstorms)
62
- end
63
- # these are the icon codes that indicate "sun", used by sunny? function
64
- def self._sunny_icon_codes
65
- %w(clear mostlysunny partlysunny sunny partlycloudy)
66
- end
67
-
68
- def self._build_extra(measurement, result, metric=true)
69
- #raise ArgumentError unless measurement.is_a?(Data::Measurement)
70
- #raise ArgumentError unless query.is_a?(Barometer::Query)
71
-
72
- # use todays sun data for all future days
73
- if measurement.forecast && measurement.current.sun
74
- measurement.forecast.each do |forecast|
75
- forecast.sun = measurement.current.sun
76
- end
77
- end
78
-
79
- measurement
80
- end
81
-
82
- def self._parse_full_timezone(data)
83
- raise ArgumentError unless data.is_a?(Hash)
84
- if data && data['simpleforecast'] &&
85
- data['simpleforecast']['forecastday'] &&
86
- data['simpleforecast']['forecastday'].first &&
87
- data['simpleforecast']['forecastday'].first['date']
88
- Data::Zone.new(
89
- data['simpleforecast']['forecastday'].first['date']['tz_long']
90
- )
91
- end
92
- end
93
-
94
- def self._build_links(data)
95
- links = {}
96
- if data["credit"] && data["credit_URL"]
97
- links[data["credit"]] = data["credit_URL"]
98
- end
99
- links
100
- end
101
-
102
- def self._build_current(data, metric=true)
103
- raise ArgumentError unless data.is_a?(Hash)
104
-
105
- current = Measurement::Result.new
106
- if data['observation_time'] && data['observation_time'].match(/\d/)
107
- current.updated_at = Data::LocalDateTime.parse(data['observation_time'])
108
- end
109
- current.humidity = data['relative_humidity'].to_i
110
- current.icon = data['icon'] if data['icon']
111
-
112
- current.temperature = Data::Temperature.new(metric)
113
- current.temperature << [data['temp_c'], data['temp_f']]
114
-
115
- current.wind = Data::Speed.new(metric)
116
- current.wind.mph = data['wind_mph'].to_f
117
- current.wind.degrees = data['wind_degrees'].to_i
118
- current.wind.direction = data['wind_dir']
119
-
120
- current.pressure = Data::Pressure.new(metric)
121
- current.pressure << [data['pressure_mb'], data['pressure_in']]
122
-
123
- current.dew_point = Data::Temperature.new(metric)
124
- current.dew_point << [data['dewpoint_c'], data['dewpoint_f']]
125
-
126
- current.heat_index = Data::Temperature.new(metric)
127
- current.heat_index << [data['heat_index_c'], data['heat_index_f']]
128
-
129
- current.wind_chill = Data::Temperature.new(metric)
130
- current.wind_chill << [data['windchill_c'], data['windchill_f']]
131
-
132
- current.visibility = Data::Distance.new(metric)
133
- current.visibility << [data['visibility_km'], data['visibility_mi']]
134
-
135
- current
136
- end
137
-
138
- def self._build_forecast(data, metric=true)
139
- raise ArgumentError unless data.is_a?(Hash)
140
- forecasts = Measurement::ResultArray.new
141
- # go through each forecast and create an instance
142
- if data && data['simpleforecast'] &&
143
- data['simpleforecast']['forecastday']
144
-
145
- data['simpleforecast']['forecastday'].each do |forecast|
146
- forecast_measurement = Measurement::Result.new
147
- forecast_measurement.icon = forecast['icon']
148
- forecast_measurement.date = Date.parse(forecast['date']['pretty'])
149
- forecast_measurement.pop = forecast['pop'].to_i
150
-
151
- forecast_measurement.high = Data::Temperature.new(metric)
152
- forecast_measurement.high << [forecast['high']['celsius'],forecast['high']['fahrenheit']]
153
-
154
- forecast_measurement.low = Data::Temperature.new(metric)
155
- forecast_measurement.low << [forecast['low']['celsius'],forecast['low']['fahrenheit']]
156
-
157
- forecasts << forecast_measurement
158
- end
159
- end
160
- forecasts
161
- end
162
-
163
- def self._build_location(data, geo=nil)
164
- raise ArgumentError unless data.is_a?(Hash)
165
- location = Data::Location.new
166
- if data['display_location']
167
- location.name = data['display_location']['full']
168
- location.city = data['display_location']['city']
169
- location.state_name = data['display_location']['state_name']
170
- location.state_code = data['display_location']['state']
171
- location.country_code = data['display_location']['country']
172
- location.zip_code = data['display_location']['zip']
173
- location.latitude = data['display_location']['latitude']
174
- location.longitude = data['display_location']['longitude']
175
- end
176
- location
177
- end
178
-
179
- def self._build_station(data)
180
- raise ArgumentError unless data.is_a?(Hash)
181
- station = Data::Location.new
182
- station.id = data['station_id']
183
- if data['observation_location']
184
- station.name = data['observation_location']['full']
185
- station.city = data['observation_location']['city']
186
- station.state_name = data['observation_location']['state_name']
187
- station.state_code = data['observation_location']['state']
188
- station.country_code = data['observation_location']['country']
189
- station.zip_code = data['observation_location']['zip']
190
- station.latitude = data['observation_location']['latitude']
191
- station.longitude = data['observation_location']['longitude']
192
- end
193
- station
194
- end
195
-
196
- def self._build_sun(data)
197
- raise ArgumentError unless data.is_a?(Hash)
198
- sun = nil
199
- if data
200
- if data['moon_phase']
201
- rise = Data::LocalTime.new(
202
- data['moon_phase']['sunrise']['hour'].to_i,
203
- data['moon_phase']['sunrise']['minute'].to_i
204
- ) if data['moon_phase']['sunrise']
205
- set = Data::LocalTime.new(
206
- data['moon_phase']['sunset']['hour'].to_i,
207
- data['moon_phase']['sunset']['minute'].to_i
208
- ) if data['moon_phase']['sunset']
209
- sun = Data::Sun.new(rise,set)
210
- end
211
- end
212
- sun || Data::Sun.new
213
- end
214
-
215
- # override default _fetch behavior
216
- # this service requires TWO seperate http requests (one for current
217
- # and one for forecasted weather) ... combine the results
218
- #
219
- def self._fetch(query, metric=true)
220
- result = []
221
- result << _fetch_current(query)
222
- result << _fetch_forecast(query)
223
- result
224
- end
225
-
226
- # use HTTParty to get the current weather
227
- #
228
- def self._fetch_current(query)
229
- return unless query
230
- puts "fetch wunderground current: #{query.q}" if Barometer::debug?
231
- self.get(
232
- "http://api.wunderground.com/auto/wui/geo/WXCurrentObXML/index.xml",
233
- :query => {:query => query.q},
234
- :format => :xml,
235
- :timeout => Barometer.timeout
236
- )['current_observation']
237
- end
238
-
239
- # use HTTParty to get the forecasted weather
240
- #
241
- def self._fetch_forecast(query)
242
- return unless query
243
- puts "fetch wunderground forecast: #{query.q}" if Barometer::debug?
244
- self.get(
245
- "http://api.wunderground.com/auto/wui/geo/ForecastXML/index.xml",
246
- :query => {:query => query.q},
247
- :format => :xml,
248
- :timeout => Barometer.timeout
249
- )['forecast']
250
- end
251
-
252
- # since we have two sets of data, override these calls to choose the
253
- # right set of data
254
- #
255
- def self._current_result(data); data[0]; end
256
- def self._forecast_result(data=nil); data[1]; end
257
- def self._location_result(data=nil); data[0]; end
258
- def self._station_result(data=nil); data[0]; end
259
- def self._links_result(data=nil); data[0]; end
260
- def self._sun_result(data=nil); data[1]; end
261
- def self._timezone_result(data=nil); data[1]; end
262
-
263
- end
264
- end