weather_judge 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9a7cc48f83c00173d4ac5eb1d72ccb336b8ea206
4
- data.tar.gz: 25131c80b1435c676367b06be003f62bbb5c950b
3
+ metadata.gz: b16a105944c44f8c8570ceecaf92d4bce60d87e9
4
+ data.tar.gz: 2083d9db3e5990d7a1c7ef7f9e7a604310f917b8
5
5
  SHA512:
6
- metadata.gz: 131fdfde7a5ad13aa8478df225e564f1a661147d224d215b6d71010033287d38dac31fc1cc9216405fd9f90d8a2a1c4de8041d01b63a745f37cdba92532a3aca
7
- data.tar.gz: de6e5d2dd793f317d9b645867c1b669d9051e28ea564d240ed85769818be15663c2d3924ddbaa28f71bb16bb240f50cc663a7819221669028b057fafebda8c89
6
+ metadata.gz: 69ee399124f40a141c80f6accbda48b3e2fc48196d213e67c1dc039c9fbe9facc4ccb2a10be3c2d0cb06271ba9011c7dea2d1dc9eaaf555920c3a87885957773
7
+ data.tar.gz: 5fed51dce6328ed31f0086c73cbb1b41556cd32c613d49a64593026ea7929eb5dfee2f6cf963cc287cabf717776077fac24c902f7d212fe676c5c44c45f4750c
data/README.md CHANGED
@@ -2,18 +2,26 @@
2
2
 
3
3
  This gem retrieves weather forecasting data from Forecast.IO via [forecast-ruby](https://github.com/darkskyapp/forecast-ruby)
4
4
  using longitude and latitude and returns an overall score. The following criteria are used to judge
5
- the quality of weather. The total score is up to 100.
5
+ the quality of weather. The maximum score you can get is 100.
6
6
 
7
7
  - Temperature
8
8
  - Sky Cover
9
9
  - Wind speed
10
- - Change of Rain
10
+ - Chance of Rain
11
11
 
12
12
  Currently it only evaluates today's data but I plan on adding an ability to take a specified date. This is
13
- more of a proof of concept at this point. Since there are four criteria at the moment, each of them holds
14
- up to 25 points. Optimal weather is considered as a day with comfortable temperature, less than 15 mph wind,
13
+ more of a proof of concept at this point. Since there are four criteria, each criteria can be given
14
+ up to 25 points. By default, optimal weather is considered as a day with comfortable temperature (67-77F), less than 15 mph wind,
15
15
  low chance of rain, and low sky cover.
16
16
 
17
+ ## Why I Developed This Gem
18
+
19
+ I currently live in Portland, OR, USA, where we have access to great outdoors. You can easily drive to the
20
+ coast (Pacific Ocean) or the mountains (Cascade Range) within a few hours. Consequently, we have
21
+ micro-climates and the weather can vary depending on where you are. I like to hike a lot, so I need
22
+ to know where would be the best place to go for a day trip easily. I plan to use this gem for an app
23
+ that will rank specified locations to help me decide where to go on the day of the trip.
24
+
17
25
  ## Installation
18
26
 
19
27
  Add this line to your application's Gemfile:
@@ -31,21 +39,54 @@ Or install it yourself as:
31
39
  $ gem install weather_judge
32
40
 
33
41
  ## Usage
34
- `WeatherJudge` returns overall weather score, and scores of weather aspect.
42
+ `WeatherJudge` takes longitude and latitude as input and then returns an overall weather score, and scores of weather aspect via `WeatherData` class.
35
43
 
36
44
  Please see [Forecast IO's documentation](https://developer.forecast.io/) for creating an api key.
37
45
 
46
+ To configure you can do:
47
+
48
+ ```ruby
49
+ WeatherJudge.configure do |configuration|
50
+ configuration.forecast_io_api_key = `(your api key here)`
51
+ configuration.max_cloud_cover = 0.60
52
+ configuration.max_percent_rain = 0.30
53
+ configuration.max_wind_speed = 22
54
+ configuration.ideal_temp_range = { min: 50, max: 80}
55
+ configuration.temp_range_delta = 10
56
+ end
57
+ ```
58
+
59
+ or
60
+
38
61
  ```ruby
39
- WeatherJudge.forecast_io_api_key = '(your api key here)'
40
- data = WeatherJudge.run(44, -122)
62
+ WeatherJudge.forecast_io_api_key = `(your api key here)`
63
+ WeatherJudge.max_cloud_cover = 0.60
64
+ # and so forth
65
+ ```
66
+
67
+ More details on configuration
68
+ - `max_cloud_cover`: Maximum cloud cover you are willing to tolerate. A decimal number between 0 to 1
69
+ - `max_percent_rain`: Maximum change of rain you are willing to tolerate. A decimal number between 0 to 1
70
+ - `max_wind_speed`: Maximum wind speed you are willing to tolerate. Default is 15 mph.
71
+ - `ideal_temp_range`: Ideal temperature range in fahrenheit expressed in hash
72
+ - `temp_range_delta`: The delta for slightly less than ideal temperate range in fahrenheit
73
+
74
+ To run, you need to pass in a valid coordinates.
75
+
76
+ ```ruby
77
+ data = WeatherJudge.run(44.123, -122.123)
41
78
  # => Returns `WeatherData` object
42
79
 
43
80
  data.total_location_score
44
- # => returns a score of 0 - 100
81
+ # => returns a score of up to 100
45
82
  ```
46
83
 
47
- Available methods for `WeatherData`
48
- - `raw_data`
84
+ List of available methods for `WeatherData`
85
+ - `raw_data` returns forecast data in `Hashie` (More info on Hashie [here](https://github.com/intridea/hashie)) . Example:
86
+ ```
87
+ => #<Hashie::Mash apparentTemperatureMax=85.83 apparentTemperatureMaxTime=1472702400 apparentTemperatureMin=79.79 apparentTemperatureMinTime=1472734800 cloudCover=0.17 dewPoint=70.42 humidity=0.72 icon="partly-cloudy-night" moonPhase=0.99 ozone=280.5 precipIntensity=0.001 precipIntensityMax=0.0025 precipIntensityMaxTime=1472677200 precipProbability=0.07 precipType="rain" pressure=1009.95 summary="Partly cloudy in the morning." sunriseTime=1472673538 sunsetTime=1472719928 temperatureMax=81.76 temperatureMaxTime=1472702400 temperatureMin=79.79 temperatureMinTime=1472734800 time=1472652000 windBearing=186 windSpeed=4.09>
88
+
89
+ ```
49
90
  - `total_location_score`
50
91
  - `cloud_cover_score`
51
92
  - `wind_score`
@@ -64,11 +105,11 @@ update the version number in `version.rb`, and then run `bundle exec rake releas
64
105
  git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
65
106
 
66
107
  ## Future Plans/Disclaimer
67
- The current state of this gem is more of a proof of concept. This gem was originally developed to be
68
- used in my personal project for ranking overall weather of different locations, but feel free to use
69
- it for any purpose. This gem will be evolving in the near future. A couple of obvious future plans are:
70
- - Add ability to change preferred weather aspects for scoring
108
+ This gem was originally developed to be used in my personal project for ranking overall weather of
109
+ different locations, but feel free to use it for any other purpose. This gem will be evolving in the
110
+ near future. A few of obvious future plans are:
71
111
  - Add ability to specify a date for retrieving scored data
112
+ - Other weather criteria to evaluate
72
113
 
73
114
  ## Contributing
74
115
 
@@ -1,9 +1,40 @@
1
1
  module WeatherJudge
2
2
  module Configuration
3
- attr_writer :forecast_io_api_key
3
+ attr_writer :forecast_io_api_key, :max_cloud_cover, :max_percent_rain, :max_wind_speed,
4
+ :ideal_temp_range, :temp_range_delta
5
+
6
+ # For configuring WeatherJudge with block style
7
+ def configure
8
+ yield self
9
+ end
4
10
 
5
11
  def forecast_io_api_key
6
12
  @forecast_io_api_key
7
13
  end
14
+
15
+ # Maximum cloud cover you are willing to tolerate
16
+ def max_cloud_cover
17
+ @max_cloud_cover
18
+ end
19
+
20
+ # Maximum change of rain you are willing to tolerate
21
+ def max_percent_rain
22
+ @max_percent_rain
23
+ end
24
+
25
+ # Maximum wind speed you are willing to tolerate. Default is 15mph.
26
+ def max_wind_speed
27
+ @max_wind_speed || 15
28
+ end
29
+
30
+ # Ideal temperature range in fahrenheit expressed in hash
31
+ def ideal_temp_range
32
+ @ideal_temp_range || { min: 67, max: 77 }
33
+ end
34
+
35
+ # The delta for slightly less than ideal temperate range in fahrenheit
36
+ def temp_range_delta
37
+ @temp_range_delta || 10
38
+ end
8
39
  end
9
40
  end
@@ -1,3 +1,3 @@
1
1
  module WeatherJudge
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -1,3 +1,6 @@
1
+ require 'bigdecimal'
2
+ require 'bigdecimal/util'
3
+
1
4
  # Calculates score for 4 different weather aspects: sky cover,
2
5
  # chance of rain, wind, and temperature
3
6
 
@@ -21,19 +24,17 @@ module WeatherJudge
21
24
  end
22
25
 
23
26
  def cloud_cover_score
24
- @forecast_today.cloudCover * SCORE_WEIGHT
27
+ score_from_decimal_data(WeatherJudge.max_cloud_cover, @forecast_today.cloudCover)
25
28
  end
26
29
 
27
30
  def percent_rain_score
28
- @forecast_today.precipProbability * SCORE_WEIGHT
31
+ score_from_decimal_data(WeatherJudge.max_percent_rain, @forecast_today.precipProbability)
29
32
  end
30
33
 
31
34
  def wind_score
32
35
  wind_speed = @forecast_today.windSpeed
33
- max_wind_speed = 15.to_f
34
- if wind_speed == 0
35
- SCORE_WEIGHT
36
- elsif wind_speed < max_wind_speed
36
+ max_wind_speed = WeatherJudge.max_wind_speed.to_f
37
+ if wind_speed < max_wind_speed
37
38
  ((max_wind_speed - wind_speed) / max_wind_speed) * SCORE_WEIGHT
38
39
  else
39
40
  0
@@ -41,15 +42,35 @@ module WeatherJudge
41
42
  end
42
43
 
43
44
  def temperature_score
44
- max_temperature = @forecast_today.temperatureMax
45
+ high_today = @forecast_today.temperatureMax
46
+ min_ideal_temp = WeatherJudge.ideal_temp_range[:min]
47
+ max_ideal_temp = WeatherJudge.ideal_temp_range[:max]
48
+ delta = WeatherJudge.temp_range_delta
45
49
 
46
- if max_temperature > 67 && max_temperature < 77
50
+ if high_today > min_ideal_temp && high_today < max_ideal_temp
47
51
  SCORE_WEIGHT
48
- elsif max_temperature > 55 && max_temperature < 67 || max_temperature > 77 && max_temperature < 85
52
+ elsif high_today > min_ideal_temp - delta && high_today < min_ideal_temp ||
53
+ high_today > max_ideal_temp && high_today < max_ideal_temp + delta
49
54
  SCORE_WEIGHT.to_f / 2
50
55
  else
51
56
  SCORE_WEIGHT.to_f / 4
52
57
  end
53
58
  end
59
+
60
+ private
61
+
62
+ # Calculates weather quality from decimal data, with an assumption that larger the
63
+ # data value the worse. E.g. (80% cloud cover returns smaller score than 50% cloud cover.)
64
+ def score_from_decimal_data(max_allowed, data)
65
+ if !max_allowed.nil?
66
+ if data < max_allowed
67
+ (((max_allowed.to_d - data) / max_allowed) * SCORE_WEIGHT).to_f
68
+ else
69
+ 0
70
+ end
71
+ else
72
+ ((1.to_d - data) * SCORE_WEIGHT).to_f
73
+ end
74
+ end
54
75
  end
55
76
  end
data/lib/weather_judge.rb CHANGED
@@ -10,11 +10,26 @@ module WeatherJudge
10
10
 
11
11
  # Retrieves WeatherData object for today's forecast given latitude and longitude.
12
12
  def run(latitude, longitude)
13
+ validate_coordinates(latitude, longitude)
14
+
13
15
  ForecastIO.api_key = WeatherJudge.forecast_io_api_key
14
16
  forecast = ForecastIO.forecast(latitude, longitude, params: { exclude: 'hourly,minutely,alerts,flags'})
17
+
18
+ if forecast.nil?
19
+ raise StandardError.new("Unable to obtain forecast! Check your network connectivity and API key")
20
+ end
21
+
15
22
  @forecast_today = forecast.daily.data.first
16
23
 
17
24
  WeatherData.new(@forecast_today)
18
25
  end
26
+
27
+ private
28
+
29
+ def validate_coordinates(latitude, longitude)
30
+ unless latitude >= -90 && latitude <= 90 && longitude >= -180 && longitude <= 180
31
+ raise ArgumentError.new("Invalid coordinates!")
32
+ end
33
+ end
19
34
  end
20
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: weather_judge
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Makoto Scott-Hinkle
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-08-29 00:00:00.000000000 Z
11
+ date: 2016-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler