barometer 0.8.0 → 0.9.0

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 (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