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
@@ -0,0 +1,27 @@
1
+ require 'nokogiri'
2
+ require 'nori'
3
+ require 'rexml/document'
4
+
5
+ module Barometer
6
+ module Utils
7
+ module XmlReader
8
+ def self.parse(xml, *nodes_to_remove)
9
+ xml_reader = Nori.new(
10
+ parser: :nokogiri,
11
+ strip_namespaces: true
12
+ )
13
+ output = xml_reader.parse(xml)
14
+
15
+ nodes_to_remove.each do |node|
16
+ output = output.fetch(node, output)
17
+ end
18
+
19
+ if block_given? && output
20
+ output = yield(output)
21
+ end
22
+
23
+ output
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,30 @@
1
+ module Barometer
2
+ module Utils
3
+ class ZoneCodeLookup
4
+ @@zone_codes_file = File.expand_path(
5
+ File.join(File.dirname(__FILE__), 'translations', 'zone_codes.yml'))
6
+ @@zone_codes = nil
7
+
8
+ def self._load_zone_codes
9
+ $:.unshift(File.dirname(__FILE__))
10
+ @@zone_codes ||= YAML.load_file(@@zone_codes_file)
11
+ end
12
+
13
+ def self.exists?(code)
14
+ _load_zone_codes unless @@zone_codes
15
+ (::Time.zone_offset(code.to_s) || @@zone_codes && @@zone_codes.has_key?(code))
16
+ end
17
+
18
+ # Known conflicts:
19
+ # IRT (ireland and india)
20
+ # CST (central standard time, china standard time)
21
+ #
22
+ def self.offset(code)
23
+ # http://www.timeanddate.com/library/abbreviations/timezones/
24
+ # http://www.worldtimezone.com/wtz-names/timezonenames.html
25
+ _load_zone_codes unless @@zone_codes
26
+ ::Time.zone_offset(code) || ((@@zone_codes[code.to_s.upcase] || 0) * 60 * 60)
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Barometer
2
- VERSION = '0.8.0'
2
+ VERSION = '0.9.0'
3
3
  end
@@ -1,211 +1,82 @@
1
1
  module Barometer
2
- #
3
- # Weather
4
- #
5
- # holds all the measurements taken and provdes
6
- # methods to interact with the data
7
- #
8
2
  class Weather
9
-
10
- attr_accessor :measurements
3
+ attr_accessor :responses
11
4
  attr_accessor :start_at, :end_at
12
5
 
13
- def initialize; @measurements = []; end
14
-
15
- # the default measurement is the first successful measurement
16
- #
17
- def default
18
- return nil unless self.sources
19
- self.source(self.sources.first)
6
+ def initialize(units=:metric)
7
+ @units = units
8
+ @responses = []
20
9
  end
21
10
 
22
- # find the measurement for the given source, if it exists
23
- #
24
11
  def source(source)
25
- raise ArgumentError unless (source.is_a?(String) || source.is_a?(Symbol))
26
- @measurements.each do |measurement|
27
- return measurement if measurement.source == source.to_sym
28
- end
29
- nil
12
+ responses.detect{|response| response.source == source}
30
13
  end
31
14
 
32
- # list successful sources
33
- #
34
- def sources
35
- @measurements.collect {|m| m.source.to_sym if m.success?}.compact
15
+ def success?
16
+ responses.any?(&:success?)
36
17
  end
37
18
 
38
- #
39
- # Quick access methods
40
- #
19
+ def current
20
+ successful_responses.first.current if successful_responses.any?
21
+ end
41
22
 
42
- def metric?; self.default ? self.default.metric? : true; end
43
- def current; (default = self.default) ? default.current : nil; end
44
- def forecast; (default = self.default) ? default.forecast : nil; end
45
- def now; self.current; end
23
+ def forecast
24
+ successful_responses.first.forecast if successful_responses.any?
25
+ end
46
26
 
47
27
  def today
48
- default = self.default
49
- default && default.forecast ? default.forecast[0] : nil
28
+ successful_responses.first.forecast[0] if successful_responses.any?
50
29
  end
51
30
 
52
31
  def tomorrow
53
- default = self.default
54
- default && default.forecast ? default.forecast[1] : nil
32
+ successful_responses.first.forecast[1] if successful_responses.any?
55
33
  end
56
34
 
57
- # measurement search
58
- # this will search the default measurements forecasts looking for
59
- # the matching date
60
- #
61
35
  def for(query)
62
- default = self.default
63
- default && default.forecast ? default.for(query) : nil
36
+ successful_responses.first.for(query) if successful_responses.any?
64
37
  end
65
38
 
39
+ def temperature; average(:temperature, Data::Temperature); end
40
+ def dew_point; average(:dew_point, Data::Temperature); end
41
+ def heat_index; average(:heat_index, Data::Temperature); end
42
+ def wind_chill; average(:wind_chill, Data::Temperature); end
43
+ def pressure; average(:pressure, Data::Pressure); end
44
+ def visibility; average(:visibility, Data::Distance); end
45
+ def wind; average(:wind, Data::Vector); end
46
+ def humidity; average(:humidity); end
66
47
 
67
- #
68
- # helper methods
69
- #
70
- # these are handy methods that can average values for successful weather
71
- # sources, or answer a simple question (ie: weather.windy?)
72
- #
73
-
74
- #
75
- # averages
76
- #
77
-
78
- # this assumes calculating for current, and that "to_f" for a value
79
- # will return the value needed
80
- # value_name = the name of the value we are averaging
81
- # if a measurement has weighting, it will respect that
82
- #
83
- def current_average(value_name)
84
- values = []
85
- @measurements.each do |measurement|
86
- if measurement.weight && measurement.weight > 1
87
- measurement.weight.times do
88
- values << measurement.current.send(value_name).to_f if measurement.success? &&
89
- measurement.current.send(value_name)
90
- end
91
- else
92
- values << measurement.current.send(value_name).to_f if measurement.success? &&
93
- measurement.current.send(value_name)
94
- end
95
- end
96
- values.compact!
97
- return nil unless values && values.size > 0
98
- values.inject(0.0) { |sum,v| sum += v if v } / values.size
99
- end
48
+ private
100
49
 
101
- def average(value_name, do_average=true, class_name=nil)
102
- if class_name
103
- if do_average
104
- avg = Data.const_get(class_name).new(self.metric?)
105
- avg << self.current_average(value_name)
106
- else
107
- avg = self.now.send(value_name)
108
- end
109
- else
110
- avg = (do_average ? self.current_average(value_name) : self.now.send(value_name))
111
- end
112
- avg
50
+ def successful_responses
51
+ @successful_responses ||= responses.select(&:success?)
113
52
  end
114
53
 
115
- # average of all values
116
- #
117
- def humidity(do_average=true); average("humidity",do_average); end
118
- def temperature(do_average=true); average("temperature",do_average,"Temperature"); end
119
- def wind(do_average=true); average("wind",do_average,"Speed"); end
120
- def pressure(do_average=true); average("pressure",do_average,"Pressure"); end
121
- def dew_point(do_average=true); average("dew_point",do_average,"Temperature"); end
122
- def heat_index(do_average=true); average("heat_index",do_average,"Temperature"); end
123
- def wind_chill(do_average=true); average("wind_chill",do_average,"Temperature"); end
124
- def visibility(do_average=true); average("visibility",do_average,"Distance"); end
125
-
126
- #
127
- # quick access methods
128
- #
129
-
130
- # what is the current local time and date?
131
- # def time
132
- # end
133
-
134
- # def icon
135
- # self.current.icon
136
- # end
137
-
138
- #
139
- # simple questions
140
- # pass the question on to each successful measurement until we get an answer
141
- #
142
-
143
- def windy?(time_string=nil, threshold=10)
144
- local_datetime = Data::LocalDateTime.parse(time_string)
145
- raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
146
- raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
147
-
148
- is_windy = nil
149
- @measurements.each do |measurement|
150
- if measurement.success?
151
- is_windy = measurement.windy?(local_datetime, threshold)
152
- return is_windy if !is_windy.nil?
153
- end
154
- end
155
- is_windy
54
+ def average(field, data_class=nil)
55
+ return if successful_responses.empty?
56
+ value = raw_average(field)
57
+ data_class ? data_class.new(@units, value) : value
156
58
  end
157
59
 
158
- def wet?(time_string=nil, threshold=50)
159
- local_datetime = Data::LocalDateTime.parse(time_string)
160
- raise ArgumentError unless (threshold.is_a?(Fixnum) || threshold.is_a?(Float))
161
- raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
162
-
163
- is_wet = nil
164
- @measurements.each do |measurement|
165
- if measurement.success?
166
- is_wet = measurement.wet?(local_datetime, threshold)
167
- return is_wet if !is_wet.nil?
168
- end
169
- end
170
- is_wet
60
+ def raw_average(field)
61
+ weighted_value(field) / total_weight(field)
171
62
  end
172
63
 
173
- def day?(time_string=nil)
174
- local_datetime = Data::LocalDateTime.parse(time_string)
175
- raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
176
-
177
- is_day = nil
178
- @measurements.each do |measurement|
179
- if measurement.success?
180
- is_day = measurement.day?(local_datetime)
181
- return is_day if !is_day.nil?
182
- end
64
+ def total_weight(field)
65
+ successful_responses.inject(0) do |sum, response|
66
+ sum + (response.current.send(field) ? response.weight : 0)
183
67
  end
184
- is_day
185
68
  end
186
69
 
187
- def night?(time_string=nil)
188
- local_datetime = Data::LocalDateTime.parse(time_string)
189
- raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
190
- is_day = self.day?(local_datetime)
191
- is_day.nil? ? nil : !is_day
192
- end
193
-
194
- def sunny?(time_string=nil)
195
- local_datetime = Data::LocalDateTime.parse(time_string)
196
- raise ArgumentError unless (local_datetime.nil? || local_datetime.is_a?(Data::LocalDateTime))
197
-
198
- is_sunny = nil
199
- @measurements.each do |measurement|
200
- if measurement.success?
201
- return false if self.day?(local_datetime) == false
202
- is_sunny = measurement.sunny?(local_datetime)
203
- return is_sunny if !is_sunny.nil?
204
- end
70
+ def weighted_value(field)
71
+ successful_responses.inject(0) do |sum, response|
72
+ sum + (value_in_correct_units(response, field).to_f * response.weight)
205
73
  end
206
- is_sunny
207
74
  end
208
75
 
76
+ def value_in_correct_units(response, field)
77
+ value = response.current.send(field)
78
+ value = value.send(@units) if value.respond_to?(@units)
79
+ value
80
+ end
209
81
  end
210
-
211
82
  end
@@ -0,0 +1,41 @@
1
+ require_relative 'weather_services/base'
2
+ require_relative 'weather_services/response'
3
+
4
+ module Barometer
5
+ module WeatherService
6
+ def self.services=(services)
7
+ @@services = services
8
+ end
9
+
10
+ def self.services
11
+ @@services ||= Utils::VersionedRegistration.new
12
+ end
13
+
14
+ def self.register(key, *args, &block)
15
+ if block_given?
16
+ services.register(key, *args, &block)
17
+ elsif args.size > 0
18
+ services.register(key, *args)
19
+ else
20
+ raise ArgumentError
21
+ end
22
+ end
23
+
24
+ def self.source(key, version=nil)
25
+ services.find(key, version) or raise NotFound
26
+ end
27
+
28
+ def self.new(*args)
29
+ Base.new(*args)
30
+ end
31
+
32
+ class KeyRequired < StandardError; end
33
+ class NotFound < StandardError; end
34
+ end
35
+ end
36
+
37
+ require_relative 'weather_services/wunderground_v1'
38
+ require_relative 'weather_services/yahoo'
39
+ require_relative 'weather_services/weather_bug'
40
+ require_relative 'weather_services/noaa'
41
+ require_relative 'weather_services/forecast_io'
@@ -0,0 +1,50 @@
1
+ module Barometer
2
+ module WeatherService
3
+ class Base
4
+ def initialize(source, version=nil)
5
+ @source = source
6
+ @service = WeatherService.source(@source, version)
7
+ end
8
+
9
+ def measure(query, options={})
10
+ @response = Barometer::Response.new
11
+
12
+ record_time do
13
+ measure_and_record_status(query, options)
14
+ end
15
+
16
+ @response.weight = options.fetch(:weight, nil)
17
+ @response.source = @source
18
+ @response
19
+ end
20
+
21
+ private
22
+
23
+ def measure_and_record_status(query, options)
24
+ capture_status_code do
25
+ @response = @service.call(query, options)
26
+ end
27
+ end
28
+
29
+ def capture_status_code
30
+ yield
31
+ @response.status_code = @response.complete? ? 200 : 204
32
+ rescue KeyRequired
33
+ @response.status_code = 401
34
+ rescue Query::ConversionNotPossible
35
+ @response.status_code = 406
36
+ rescue Query::UnsupportedRegion
37
+ @response.status_code = 406
38
+ rescue Timeout::Error
39
+ @response.status_code = 408
40
+ end
41
+
42
+ def record_time
43
+ response_started_at = Time.now.utc
44
+ yield
45
+ @response.response_started_at = response_started_at
46
+ @response.response_ended_at = Time.now.utc
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'forecast_io/api'
2
+ require_relative 'forecast_io/response'
3
+
4
+ module Barometer
5
+ module WeatherService
6
+ class ForecastIo
7
+ def self.call(query, config={})
8
+ ForecastIo.new(query, config).measure!
9
+ end
10
+
11
+ def initialize(query, config={})
12
+ @query = query
13
+ @apikey = config[:keys][:api] if config[:keys]
14
+ end
15
+
16
+ def measure!
17
+ validate_key!
18
+
19
+ api = ForecastIo::Api.new(query, apikey)
20
+ ForecastIo::Response.new.parse(api.get)
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :query, :apikey
26
+
27
+ def validate_key!
28
+ unless apikey && !apikey.empty?
29
+ raise KeyRequired
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ Barometer::WeatherService.register(:forecast_io, Barometer::WeatherService::ForecastIo)