tikaro-sandex 0.0.0 → 0.0.1

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.
@@ -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