simple_metar_parser 0.0.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.
- data/Gemfile +13 -0
- data/Gemfile.lock +28 -0
- data/LICENSE.txt +165 -0
- data/README.rdoc +55 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/simple_metar_parser.rb +7 -0
- data/lib/simple_metar_parser/metar.rb +120 -0
- data/lib/simple_metar_parser/metar/base.rb +24 -0
- data/lib/simple_metar_parser/metar/clouds.rb +81 -0
- data/lib/simple_metar_parser/metar/metar_city.rb +36 -0
- data/lib/simple_metar_parser/metar/metar_other.rb +27 -0
- data/lib/simple_metar_parser/metar/metar_specials.rb +210 -0
- data/lib/simple_metar_parser/metar/metar_time.rb +40 -0
- data/lib/simple_metar_parser/metar/pressure.rb +52 -0
- data/lib/simple_metar_parser/metar/temperature.rb +101 -0
- data/lib/simple_metar_parser/metar/visibility.rb +47 -0
- data/lib/simple_metar_parser/metar/wind.rb +144 -0
- data/lib/simple_metar_parser/parser.rb +7 -0
- data/lib/simple_metar_parser/tmp/tmp.rb +34 -0
- metadata +114 -0
@@ -0,0 +1,101 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module SimpleMetarParser
|
4
|
+
class Temperature < Base
|
5
|
+
|
6
|
+
def reset
|
7
|
+
@temperature = nil
|
8
|
+
@dew = nil
|
9
|
+
end
|
10
|
+
|
11
|
+
# Temperature in C
|
12
|
+
attr_reader :temperature
|
13
|
+
alias :degrees :temperature
|
14
|
+
|
15
|
+
# Dew temperature
|
16
|
+
attr_reader :dew
|
17
|
+
|
18
|
+
# Relative humidity
|
19
|
+
attr_reader :humidity
|
20
|
+
|
21
|
+
# Wind chill index
|
22
|
+
attr_reader :wind_chill
|
23
|
+
|
24
|
+
# US Wind chill index
|
25
|
+
attr_reader :wind_chill_us
|
26
|
+
|
27
|
+
def decode_split(s)
|
28
|
+
# Temperature in Celsius degrees
|
29
|
+
if s =~ /^(M?)(\d{2})\/(M?)(\d{2})$/
|
30
|
+
if $1 == "M"
|
31
|
+
@temperature = -1.0 * $2.to_f
|
32
|
+
else
|
33
|
+
@temperature = $2.to_f
|
34
|
+
end
|
35
|
+
|
36
|
+
if $3 == "M"
|
37
|
+
@dew = -1.0 * $4.to_f
|
38
|
+
else
|
39
|
+
@dew = $4.to_f
|
40
|
+
end
|
41
|
+
|
42
|
+
return
|
43
|
+
end
|
44
|
+
|
45
|
+
# shorter version
|
46
|
+
if s =~ /^(M?)(\d{2})\/$/
|
47
|
+
if $1 == "M"
|
48
|
+
@temperature = -1.0 * $2.to_f
|
49
|
+
else
|
50
|
+
@temperature = $2.to_f
|
51
|
+
end
|
52
|
+
|
53
|
+
return
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def post_process
|
58
|
+
calculate_humidity
|
59
|
+
calculate_wind_chill
|
60
|
+
end
|
61
|
+
|
62
|
+
def calculate_humidity
|
63
|
+
# Calculate relative humidity
|
64
|
+
return if self.temperature.nil? or self.dew.nil?
|
65
|
+
|
66
|
+
# http://github.com/brandonh/ruby-metar/blob/master/lib/metar.rb
|
67
|
+
# http://www.faqs.org/faqs/meteorology/temp-dewpoint/
|
68
|
+
|
69
|
+
es0 = 6.11 # hPa
|
70
|
+
t0 = 273.15 # kelvin
|
71
|
+
td = self.dew + t0 # kelvin
|
72
|
+
t = self.temperature + t0 # kelvin
|
73
|
+
lv = 2500000 # joules/kg
|
74
|
+
rv = 461.5 # joules*kelvin/kg
|
75
|
+
e = es0 * Math::exp(lv/rv * (1.0/t0 - 1.0/td))
|
76
|
+
es = es0 * Math::exp(lv/rv * (1.0/t0 - 1.0/t))
|
77
|
+
rh = 100 * e/es
|
78
|
+
|
79
|
+
@humidity = rh.round
|
80
|
+
end
|
81
|
+
|
82
|
+
def calculate_wind_chill
|
83
|
+
return if self.temperature.nil? or self.parent.wind.wind_speed.nil?
|
84
|
+
return if self.temperature > 10 or self.parent.wind.wind_speed_kmh < 4.8
|
85
|
+
|
86
|
+
# http://en.wikipedia.org/wiki/Wind_chill
|
87
|
+
v = self.parent.wind.wind_speed
|
88
|
+
ta = self.temperature
|
89
|
+
|
90
|
+
@wind_chill_us = 13.12 +
|
91
|
+
0.6215 * ta -
|
92
|
+
11.37 * v +
|
93
|
+
0.3965 * ta * v
|
94
|
+
|
95
|
+
@wind_chill = (10.0 * Math.sqrt(v) - v + 10.5)*(33.0 - ta)
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module SimpleMetarParser
|
4
|
+
class Visibility < Base
|
5
|
+
|
6
|
+
# max visibility
|
7
|
+
MAX_VISIBILITY = 10_000
|
8
|
+
|
9
|
+
# If visibility is greater than this it assume it is maximum
|
10
|
+
NEARLY_MAX_VISIBILITY = 9_500
|
11
|
+
|
12
|
+
def reset
|
13
|
+
@visibility = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :visibility
|
17
|
+
|
18
|
+
def decode_split(s)
|
19
|
+
# Visibility in meters
|
20
|
+
|
21
|
+
# Europa
|
22
|
+
if s =~ /^(\d{4})$/
|
23
|
+
@visibility = $1.to_i
|
24
|
+
end
|
25
|
+
|
26
|
+
# US
|
27
|
+
if s =~ /^(\d{1,3})\/?(\d{0,2})SM$/
|
28
|
+
if $2 == ""
|
29
|
+
@visibility = $1.to_i * 1600.0
|
30
|
+
else
|
31
|
+
@visibility = $1.to_f * 1600.0 / $2.to_f
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# constant max value
|
36
|
+
if @visibility.to_i >= NEARLY_MAX_VISIBILITY
|
37
|
+
@visibility = MAX_VISIBILITY
|
38
|
+
end
|
39
|
+
|
40
|
+
if s =~ /^(CAVOK)$/
|
41
|
+
@visibility = MAX_VISIBILITY
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
@@ -0,0 +1,144 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
module SimpleMetarParser
|
4
|
+
class Wind < Base
|
5
|
+
|
6
|
+
def reset
|
7
|
+
@winds = Array.new
|
8
|
+
@winds_variable_directions = Array.new
|
9
|
+
end
|
10
|
+
|
11
|
+
KNOTS_TO_METERS_PER_SECOND = 1.85 / 3.6
|
12
|
+
KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND = 1.0 / 3.6
|
13
|
+
|
14
|
+
def decode_split(s)
|
15
|
+
decode_wind(s)
|
16
|
+
decode_wind_variable(s)
|
17
|
+
end
|
18
|
+
|
19
|
+
def post_process
|
20
|
+
recalculate_winds
|
21
|
+
end
|
22
|
+
|
23
|
+
# Wind parameters in meters per second
|
24
|
+
def decode_wind(s)
|
25
|
+
|
26
|
+
if s =~ /(\d{3})(\d{2})G?(\d{2})?(KT|MPS|KMH)/
|
27
|
+
# different units
|
28
|
+
wind = case $4
|
29
|
+
when "KT" then
|
30
|
+
$2.to_f * KNOTS_TO_METERS_PER_SECOND
|
31
|
+
when "MPS" then
|
32
|
+
$2.to_f
|
33
|
+
when "KMH" then
|
34
|
+
$2.to_f * KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND
|
35
|
+
else
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
wind_max = case $4
|
40
|
+
when "KT" then
|
41
|
+
$3.to_f * KNOTS_TO_METERS_PER_SECOND
|
42
|
+
when "MPS" then
|
43
|
+
$3.to_f
|
44
|
+
when "KMH" then
|
45
|
+
$3.to_f * KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND
|
46
|
+
else
|
47
|
+
nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# wind_max is not less than normal wind
|
51
|
+
if wind_max < wind or wind_max.nil?
|
52
|
+
wind_max = wind
|
53
|
+
end
|
54
|
+
|
55
|
+
@winds << {
|
56
|
+
:wind => wind,
|
57
|
+
:wind_max => wind_max,
|
58
|
+
:wind_direction => $1.to_i
|
59
|
+
}
|
60
|
+
end
|
61
|
+
|
62
|
+
# variable/unknown direction
|
63
|
+
if s =~ /VRB(\d{2})(KT|MPS|KMH)/
|
64
|
+
wind = case $2
|
65
|
+
when "KT" then
|
66
|
+
$1.to_f * KNOTS_TO_METERS_PER_SECOND
|
67
|
+
when "MPS" then
|
68
|
+
$1.to_f
|
69
|
+
when "KMH" then
|
70
|
+
$1.to_f * KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
@winds << {
|
76
|
+
:wind => wind
|
77
|
+
}
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Variable wind direction
|
83
|
+
def decode_wind_variable(s)
|
84
|
+
if s =~ /(\d{3})V(\d{3})/
|
85
|
+
@winds_variable_directions << {
|
86
|
+
:wind_variable_direction_from => $1.to_i,
|
87
|
+
:wind_variable_direction_to => $2.to_i,
|
88
|
+
:wind_direction => ($1.to_i + $2.to_i) / 2,
|
89
|
+
:wind_variable => true
|
90
|
+
}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Calculate wind parameters, some metar string has multiple winds recorded
|
95
|
+
def recalculate_winds
|
96
|
+
@wind = @winds.collect { |w| w[:wind] }.inject(0) { |b, i| b + i } / @winds.size
|
97
|
+
if @winds.size == 1
|
98
|
+
@wind_direction = @winds.first[:wind_direction]
|
99
|
+
else
|
100
|
+
@wind_direction = nil
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Wind speed in meters per second
|
105
|
+
attr_reader :wind
|
106
|
+
alias_method :wind_speed, :wind
|
107
|
+
|
108
|
+
# Direction of wind
|
109
|
+
attr_reader :wind_direction
|
110
|
+
|
111
|
+
# Wind speed in knots
|
112
|
+
def wind_speed_knots
|
113
|
+
return self.wind if self.wind.nil?
|
114
|
+
return self.wind / KNOTS_TO_METERS_PER_SECOND
|
115
|
+
end
|
116
|
+
|
117
|
+
# Wind speed in KM/H
|
118
|
+
def wind_speed_kmh
|
119
|
+
return self.wind if self.wind.nil?
|
120
|
+
return self.wind / KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND
|
121
|
+
end
|
122
|
+
|
123
|
+
# Meters per second
|
124
|
+
def mps
|
125
|
+
self.wind
|
126
|
+
end
|
127
|
+
|
128
|
+
# Kilometers per hour
|
129
|
+
def kmh
|
130
|
+
self.wind_speed_kmh
|
131
|
+
end
|
132
|
+
|
133
|
+
# Knots
|
134
|
+
def knots
|
135
|
+
self.wind_speed_knots
|
136
|
+
end
|
137
|
+
|
138
|
+
# Wind direction
|
139
|
+
def direction
|
140
|
+
self.wind_direction
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
# If metar string is valid, processed ok with basic data, and time was correct
|
3
|
+
def valid?
|
4
|
+
if TYPE_ARCHIVED == @type
|
5
|
+
if not @city_metar.nil? and
|
6
|
+
not self.temperature.nil? and
|
7
|
+
not self.wind.nil? and
|
8
|
+
not self.time_from.nil? and
|
9
|
+
self.time_from <= Time.now
|
10
|
+
return true
|
11
|
+
end
|
12
|
+
|
13
|
+
elsif TYPE_FRESH == @type
|
14
|
+
# time should be near now
|
15
|
+
if not @city_metar.nil? and
|
16
|
+
|
17
|
+
self.time_from <= Time.now and
|
18
|
+
self.time_from >= (Time.now - 3*24*3600)
|
19
|
+
return true
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
return false
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
|
29
|
+
# Decode runway data. Not yet implemented.
|
30
|
+
def decode_runway(s)
|
31
|
+
# BIAR 130700Z 17003KT 0350 R01/0900V1500U +SN VV001 M04/M04 Q0996
|
32
|
+
# Runway 01, touchdown zone visual range is variable from a minimum of 0900 meters until a maximum of 1500 meters, and increasing
|
33
|
+
# http://heras-gilsanz.com/manuel/METAR-Decoder.html
|
34
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: simple_metar_parser
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Aleksander Kwiatkowski
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-26 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: &28881540 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 2.3.0
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *28881540
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: bundler
|
27
|
+
requirement: &28881060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.0.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *28881060
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: jeweler
|
38
|
+
requirement: &28880580 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.6.4
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *28880580
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rcov
|
49
|
+
requirement: &18380860 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *18380860
|
58
|
+
description: Gem for parsing METARs fast and simple.
|
59
|
+
email: bobikx@poczta.fm
|
60
|
+
executables: []
|
61
|
+
extensions: []
|
62
|
+
extra_rdoc_files:
|
63
|
+
- LICENSE.txt
|
64
|
+
- README.rdoc
|
65
|
+
files:
|
66
|
+
- Gemfile
|
67
|
+
- Gemfile.lock
|
68
|
+
- LICENSE.txt
|
69
|
+
- README.rdoc
|
70
|
+
- Rakefile
|
71
|
+
- VERSION
|
72
|
+
- lib/simple_metar_parser.rb
|
73
|
+
- lib/simple_metar_parser/metar.rb
|
74
|
+
- lib/simple_metar_parser/metar/base.rb
|
75
|
+
- lib/simple_metar_parser/metar/clouds.rb
|
76
|
+
- lib/simple_metar_parser/metar/metar_city.rb
|
77
|
+
- lib/simple_metar_parser/metar/metar_other.rb
|
78
|
+
- lib/simple_metar_parser/metar/metar_specials.rb
|
79
|
+
- lib/simple_metar_parser/metar/metar_time.rb
|
80
|
+
- lib/simple_metar_parser/metar/pressure.rb
|
81
|
+
- lib/simple_metar_parser/metar/temperature.rb
|
82
|
+
- lib/simple_metar_parser/metar/visibility.rb
|
83
|
+
- lib/simple_metar_parser/metar/wind.rb
|
84
|
+
- lib/simple_metar_parser/parser.rb
|
85
|
+
- lib/simple_metar_parser/tmp/tmp.rb
|
86
|
+
homepage: http://github.com/akwiatkowski/simple_metar_parser
|
87
|
+
licenses:
|
88
|
+
- LGPLv3
|
89
|
+
post_install_message:
|
90
|
+
rdoc_options: []
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
hash: 2798011357648341845
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ! '>='
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: '0'
|
108
|
+
requirements: []
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.8.15
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Simple METAR parser
|
114
|
+
test_files: []
|