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.
- data/README.rdoc +5 -4
- data/VERSION.yml +1 -1
- data/lib/sandex.rb +72 -11
- data/lib/sandex/fanger_box.rb +50 -0
- metadata +4 -2
data/README.rdoc
CHANGED
@@ -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
|
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
|
-
-
|
17
|
-
|
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
|
|
data/VERSION.yml
CHANGED
data/lib/sandex.rb
CHANGED
@@ -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
|
-
|
20
|
-
|
21
|
-
|
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
|
-
|
24
|
-
|
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.
|
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-
|
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
|