tikaro-sandex 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@
4
4
 
5
5
  == Description
6
6
 
7
- The sandex is an index of awesome your weather is, compared to the current weather in San Diego, CA. The highest possible sandex is 100%.
7
+ The sandex is an index of awesome your weather is, compared to the theoretically-perfect weather in San Diego, CA. The highest possible sandex is 100%.
8
8
 
9
9
  This score is used to answer the question: "Is it nice enough to work outside today?" If the sandex is high, yes: go work outside. That's because EVERY day is a work-outside day in San Diego.
10
10
 
@@ -13,8 +13,9 @@ Thanks to @r38y for the concept and the name.
13
13
  == Features
14
14
 
15
15
  - Given a NOAA station ID, calculate the sandex.
16
- - Currently, the sandex is a stub: 100% MINUS one percent for every degree difference (positive or negative) between your station and KSAN in San Diego.
17
- - Defaults to station KILG, near West Chester, Pennsilvania.
16
+ - Using the work of professor Ole Fanger, determine whether the temperature and relative humidity fall inside parameters for thermal comfort:
17
+ -- is the relative humidity below 60%?
18
+ -- is the temperature above minimum, but below maximum parameters?
18
19
 
19
20
  == Requirements
20
21
 
@@ -32,7 +33,7 @@ Note that the NOAA gem has some separate install requirements, and must update i
32
33
  == Usage
33
34
 
34
35
  Get the current sandex score for your location:
35
- Sandex.calculate(station_id)
36
+ Sandex.calculate(station_id, "verbose")
36
37
 
37
38
  == Contact
38
39
 
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 0
2
+ :patch: 1
3
3
  :major: 0
4
4
  :minor: 0
@@ -8,18 +8,79 @@ require 'libxml'
8
8
  require 'geokit'
9
9
  require 'noaa'
10
10
 
11
+ %w(fanger_box).each { |file| require File.join(File.dirname(__FILE__), 'sandex', file) }
12
+
11
13
  module Sandex
12
- def self.calculate(local_station='KILG')
13
- local_conditions = NOAA.current_conditions_at_station(local_station)
14
- ksan_conditions = NOAA.current_conditions_at_station('KSAN')
15
-
16
- local_temperature = local_conditions.temperature
17
- ksan_temperature = ksan_conditions.temperature
18
14
 
19
- temperature_delta = ( ksan_temperature - local_temperature ).abs
20
-
21
- sandex_score = ( 100 - temperature_delta.to_f ) / 100
15
+ def self.calculate(station='KILG', verbose=nil)
16
+
17
+ # KCOS: Colorado Springs
18
+ # KILG: West Chester
19
+ # KNYC: Central Park
20
+
21
+ sandex_score = 100
22
+ humidity_decrement = 0
23
+ temperature_decrement = 0
24
+ msg = ""
25
+
26
+ humidity_penalty = 2.5
27
+ heat_penalty = 2
28
+ cold_penalty = 1
29
+
30
+ current_conditions = NOAA.current_conditions_at_station(station)
31
+ t = current_conditions.temperature
32
+ rh = current_conditions.relative_humidity
33
+
34
+ msg += "At station #{station}, it's currently #{t} degrees and #{rh}% humidity.\n\n"
35
+
36
+ # Are we within the Fanger box?
37
+ if FangerBox.acceptable?(t,rh)
38
+ msg += "Conditions are WITHIN the Fanger Box!\n"
39
+ else
40
+
41
+ msg += "Sadly, conditions are not inside the Fanger Box:\n"
42
+
43
+ # calculate the humidity decrement
44
+ if FangerBox.too_dry?(rh)
45
+ msg += "* It's too dry.\n"
46
+ elsif FangerBox.too_humid?(rh)
47
+ humidity_delta = rh - FangerBox::HIGHEST_ALLOWABLE_HUMIDITY
48
+ humidity_decrement = humidity_delta * humidity_penalty
49
+ msg += "* It's too humid: (#{humidity_delta}% outside the Fanger Box)\n"
50
+ msg += " Decrement: #{humidity_penalty} Sandex points for each percent of humidity.\n"
51
+ msg += " Subtracting #{humidity_decrement} points from the Sandex.\n"
52
+ else
53
+ msg += "* The humidity is within the box, but the temperature is outside it.\n"
54
+ end
55
+
56
+ # calculate the temperature decrement
57
+ if FangerBox.too_cold?(t,rh)
58
+ cold_delta = FangerBox.minimum_temperature_at_humidity(rh) - t
59
+ temperature_decrement = cold_delta * cold_penalty
60
+ msg += "* It's #{cold_delta} degrees too chilly for the Fanger Box.\n"
61
+ msg += " Decrement: #{cold_penalty} Sandex points for each degree too cold.\n"
62
+ msg += " Subtracting #{temperature_decrement} points from the Sandex.\n"
63
+ elsif FangerBox.too_hot?(t,rh)
64
+ heat_delta = t - FangerBox.maximum_temperature_at_humidity(rh)
65
+ temperature_decrement = heat_delta * heat_penalty
66
+ msg += "* It's #{heat_delta} degrees too hot for the Fanger Box.\n"
67
+ msg += " Decrement: #{heat_penalty} Sandex points for each degree too hot.\n"
68
+ msg += " Subtracting #{temperature_decrement} points from the Sandex.\n"
69
+ else
70
+ msg += "* Temperature is within the Fanger box, though the humidity is outside it."
71
+ end
72
+
73
+ end
74
+
75
+ sandex_score -= humidity_decrement
76
+ sandex_score -= temperature_decrement
77
+
78
+ msg += "\nThe Sandex score for station #{station} is #{sandex_score}.\n"
22
79
 
23
- sandex_score
24
- end
80
+ puts msg if verbose == "verbose"
81
+
82
+ sandex_score
83
+
84
+ end
85
+
25
86
  end
@@ -0,0 +1,50 @@
1
+ module FangerBox
2
+
3
+ LOWEST_ALLOWABLE_HUMIDITY = 0
4
+ HIGHEST_ALLOWABLE_HUMIDITY = 60
5
+
6
+ def self.acceptable?(t,rh)
7
+ # I tried writing this as A < B < C, but it didn't work. Huh.
8
+ t > minimum_temperature_at_humidity(rh) && t < maximum_temperature_at_humidity(rh)
9
+ end
10
+
11
+ def self.rh_acceptable?(rh)
12
+ # A < B < C works here.
13
+ LOWEST_ALLOWABLE_HUMIDITY < rh < HIGHEST_ALLOWABLE_HUMIDITY
14
+ end
15
+
16
+ def self.too_dry?(rh)
17
+ # Fanger believed that humidity below 30% felt weird, but not uncomfortable.
18
+ rh <= LOWEST_ALLOWABLE_HUMIDITY
19
+ end
20
+
21
+ def self.too_humid?(rh)
22
+ # Fanger believed that humidity above 60% was pretty much always crappy.
23
+ rh > HIGHEST_ALLOWABLE_HUMIDITY
24
+ end
25
+
26
+ def self.too_cold?(t,rh)
27
+ t < minimum_temperature_at_humidity(rh)
28
+ end
29
+
30
+ def self.too_hot?(t,rh)
31
+ t > maximum_temperature_at_humidity(rh)
32
+ end
33
+
34
+ def self.minimum_temperature_at_humidity(rh)
35
+ # Based on the two bottom corners of the Fanger box:
36
+ # * 69 degrees at 30% relative humidity
37
+ # * 68 degrees at 60% relative humidity
38
+ ((1/30) * rh ) + 70
39
+ end
40
+
41
+ def self.maximum_temperature_at_humidity(rh)
42
+ # Based on the top two corners of the Fanger box:
43
+ # * 82 degrees at 30% relative humidity
44
+ # * 78 degrees at 60% relative humidity
45
+ ((4/30) * rh ) + 86
46
+ end
47
+
48
+
49
+
50
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tikaro-sandex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - tikaro
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-03-09 00:00:00 -07:00
12
+ date: 2009-03-11 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -25,6 +25,8 @@ extra_rdoc_files:
25
25
  files:
26
26
  - README.rdoc
27
27
  - VERSION.yml
28
+ - lib/sandex
29
+ - lib/sandex/fanger_box.rb
28
30
  - lib/sandex.rb
29
31
  - test/sandex_test.rb
30
32
  - test/test_helper.rb