metar-parser 1.2.0 → 1.2.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.
- checksums.yaml +4 -4
- data/Rakefile +2 -2
- data/lib/metar/data.rb +31 -32
- data/lib/metar/parser.rb +12 -11
- data/lib/metar/raw.rb +1 -1
- data/lib/metar/report.rb +3 -7
- data/lib/metar/station.rb +15 -21
- data/lib/metar/version.rb +1 -2
- data/spec/data_spec.rb +26 -0
- data/spec/{unit/distance_spec.rb → distance_spec.rb} +3 -3
- data/spec/{unit/i18n_spec.rb → i18n_spec.rb} +1 -1
- data/spec/{unit/parser_spec.rb → parser_spec.rb} +22 -8
- data/spec/pressure_spec.rb +22 -0
- data/spec/{unit/raw_spec.rb → raw_spec.rb} +33 -40
- data/spec/{unit/remark_spec.rb → remark_spec.rb} +4 -25
- data/spec/{unit/report_spec.rb → report_spec.rb} +18 -16
- data/spec/runway_visible_range_spec.rb +81 -0
- data/spec/{unit/sky_condition_spec.rb → sky_condition_spec.rb} +0 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/speed_spec.rb +45 -0
- data/spec/{unit/station_spec.rb → station_spec.rb} +83 -52
- data/spec/{unit/temperature_spec.rb → temperature_spec.rb} +7 -7
- data/spec/{unit/variable_wind_spec.rb → variable_wind_spec.rb} +10 -11
- data/spec/{unit/vertical_visibility_spec.rb → vertical_visibility_spec.rb} +1 -1
- data/spec/{unit/visibility_spec.rb → visibility_spec.rb} +16 -20
- data/spec/weather_phenomenon_spec.rb +66 -0
- data/spec/{unit/wind_spec.rb → wind_spec.rb} +10 -11
- metadata +53 -38
- data/bin/parse_raw.rb +0 -27
- data/spec/unit/pressure_spec.rb +0 -22
- data/spec/unit/runway_visible_range_spec.rb +0 -88
- data/spec/unit/speed_spec.rb +0 -45
- data/spec/unit/weather_phenomenon_spec.rb +0 -66
@@ -76,8 +76,8 @@ describe Metar::Raw::Metar do
|
|
76
76
|
let(:raw_metar) { "OPPS 3123Z 23006KT 4000 HZ SCT040 SCT100 17/12 Q1011" }
|
77
77
|
|
78
78
|
it "throws an error" do
|
79
|
-
expect { subject.time }
|
80
|
-
to raise_error(RuntimeError, /6 digit/)
|
79
|
+
expect { subject.time }
|
80
|
+
.to raise_error(RuntimeError, /6 digit/)
|
81
81
|
end
|
82
82
|
end
|
83
83
|
|
@@ -85,8 +85,8 @@ describe Metar::Raw::Metar do
|
|
85
85
|
let(:raw_metar) { "OPPS 332359Z 23006KT 4000 HZ SCT040 SCT100 17/12 Q1011" }
|
86
86
|
|
87
87
|
it "throws an error" do
|
88
|
-
expect { subject.time }
|
89
|
-
to raise_error(RuntimeError, /at most 31/)
|
88
|
+
expect { subject.time }
|
89
|
+
.to raise_error(RuntimeError, /at most 31/)
|
90
90
|
end
|
91
91
|
end
|
92
92
|
|
@@ -94,8 +94,8 @@ describe Metar::Raw::Metar do
|
|
94
94
|
let(:raw_metar) { "OPPS 002359Z 23006KT 4000 HZ SCT040 SCT100 17/12 Q1011" }
|
95
95
|
|
96
96
|
it "throws an error" do
|
97
|
-
expect { subject.time }
|
98
|
-
to raise_error(RuntimeError, /greater than 0/)
|
97
|
+
expect { subject.time }
|
98
|
+
.to raise_error(RuntimeError, /greater than 0/)
|
99
99
|
end
|
100
100
|
end
|
101
101
|
end
|
@@ -157,6 +157,10 @@ describe Metar::Raw::Noaa do
|
|
157
157
|
end
|
158
158
|
|
159
159
|
context '.fetch' do
|
160
|
+
before do
|
161
|
+
allow(ftp).to receive(:retrbinary).and_yield("chunk 1\n").and_yield("chunk 2\n")
|
162
|
+
end
|
163
|
+
|
160
164
|
it 'uses the connection' do
|
161
165
|
Metar::Raw::Noaa.fetch('the_cccc')
|
162
166
|
|
@@ -170,51 +174,40 @@ describe Metar::Raw::Noaa do
|
|
170
174
|
end
|
171
175
|
|
172
176
|
it 'returns the data' do
|
173
|
-
def ftp.retrbinary(*args, &block)
|
174
|
-
block.call "chunk 1\n"
|
175
|
-
block.call "chunk 2\n"
|
176
|
-
end
|
177
177
|
raw = Metar::Raw::Noaa.fetch('the_cccc')
|
178
178
|
|
179
179
|
expect(raw).to eq("chunk 1\nchunk 2\n")
|
180
180
|
end
|
181
181
|
|
182
|
-
|
183
|
-
|
184
|
-
@attempt
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
raise Net::FTPTempError if self.attempt == 1
|
193
|
-
block.call "chunk 1\n"
|
194
|
-
block.call "chunk 2\n"
|
182
|
+
context 'if retrieval fails once' do
|
183
|
+
before do
|
184
|
+
@attempt = 0
|
185
|
+
|
186
|
+
allow(ftp).to receive(:retrbinary) do |_args, &block|
|
187
|
+
@attempt += 1
|
188
|
+
raise Net::FTPTempError if @attempt == 1
|
189
|
+
block.call "chunk 1\n"
|
190
|
+
block.call "chunk 2\n"
|
191
|
+
end
|
195
192
|
end
|
196
|
-
|
197
|
-
raw = Metar::Raw::Noaa.fetch('the_cccc')
|
198
193
|
|
199
|
-
|
200
|
-
|
194
|
+
it 'retries' do
|
195
|
+
raw = Metar::Raw::Noaa.fetch('the_cccc')
|
201
196
|
|
202
|
-
|
203
|
-
def ftp.attempt
|
204
|
-
@attempt
|
205
|
-
end
|
206
|
-
def ftp.attempt=(a)
|
207
|
-
@attempt = a
|
197
|
+
expect(raw).to eq("chunk 1\nchunk 2\n")
|
208
198
|
end
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
199
|
+
end
|
200
|
+
|
201
|
+
context 'if retrieval fails twice' do
|
202
|
+
before do
|
203
|
+
allow(ftp).to receive(:retrbinary).and_raise(Net::FTPTempError)
|
213
204
|
end
|
214
205
|
|
215
|
-
|
216
|
-
|
217
|
-
|
206
|
+
it 'fails with an error' do
|
207
|
+
expect do
|
208
|
+
Metar::Raw::Noaa.fetch('the_cccc')
|
209
|
+
end.to raise_error(RuntimeError, /failed 2 times/)
|
210
|
+
end
|
218
211
|
end
|
219
212
|
end
|
220
213
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
|
2
|
+
|
3
3
|
describe Metar::Remark do
|
4
4
|
context '.parse' do
|
5
5
|
it 'delegate to subclasses' do
|
@@ -21,22 +21,18 @@ describe Metar::Remark do
|
|
21
21
|
expect(Metar::Remark.parse(raw)).to be_temperature_extreme(*expected)
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
24
|
end
|
26
25
|
|
27
26
|
context '24-hour maximum and minimum' do
|
28
|
-
|
29
27
|
it 'returns minimum and maximum' do
|
30
28
|
max, min = Metar::Remark.parse('400461006')
|
31
29
|
|
32
30
|
expect(max).to be_temperature_extreme(:maximum, 4.6)
|
33
31
|
expect(min).to be_temperature_extreme(:minimum, -0.6)
|
34
32
|
end
|
35
|
-
|
36
33
|
end
|
37
34
|
|
38
35
|
context 'pressure tendency' do
|
39
|
-
|
40
36
|
it 'steady_then_decreasing' do
|
41
37
|
pt = Metar::Remark.parse('58033')
|
42
38
|
|
@@ -44,31 +40,26 @@ describe Metar::Remark do
|
|
44
40
|
expect(pt.character).to eq(:steady_then_decreasing)
|
45
41
|
expect(pt.value).to eq(3.3)
|
46
42
|
end
|
47
|
-
|
48
43
|
end
|
49
44
|
|
50
45
|
context '3-hour and 6-hour precipitation' do
|
51
|
-
|
52
46
|
it '60009' do
|
53
47
|
pr = Metar::Remark.parse('60009')
|
54
|
-
|
48
|
+
|
55
49
|
expect(pr).to be_a(Metar::Precipitation)
|
56
50
|
expect(pr.period).to eq(3)
|
57
51
|
expect(pr.amount.value).to eq(0.002286)
|
58
52
|
end
|
59
|
-
|
60
53
|
end
|
61
54
|
|
62
55
|
context '24-hour precipitation' do
|
63
|
-
|
64
56
|
it '70015' do
|
65
57
|
pr = Metar::Remark.parse('70015')
|
66
|
-
|
58
|
+
|
67
59
|
expect(pr).to be_a(Metar::Precipitation)
|
68
60
|
expect(pr.period).to eq(24)
|
69
61
|
expect(pr.amount.value).to eq(0.003810)
|
70
62
|
end
|
71
|
-
|
72
63
|
end
|
73
64
|
|
74
65
|
context 'automated station' do
|
@@ -84,22 +75,18 @@ describe Metar::Remark do
|
|
84
75
|
expect(aut.type).to eq(expected[1])
|
85
76
|
end
|
86
77
|
end
|
87
|
-
|
88
78
|
end
|
89
79
|
|
90
80
|
context 'sea-level pressure' do
|
91
|
-
|
92
81
|
it 'SLP125' do
|
93
82
|
slp = Metar::Remark.parse('SLP125')
|
94
83
|
|
95
84
|
expect(slp).to be_a(Metar::SeaLevelPressure)
|
96
85
|
expect(slp.pressure.value).to eq(0.0125)
|
97
86
|
end
|
98
|
-
|
99
87
|
end
|
100
88
|
|
101
89
|
context 'hourly temperature and dew point' do
|
102
|
-
|
103
90
|
it 'T00640036' do
|
104
91
|
htm = Metar::Remark.parse('T00641036')
|
105
92
|
|
@@ -107,17 +94,12 @@ describe Metar::Remark do
|
|
107
94
|
expect(htm.temperature.value).to eq(6.4)
|
108
95
|
expect(htm.dew_point.value).to eq(-3.6)
|
109
96
|
end
|
110
|
-
|
111
97
|
end
|
112
|
-
|
113
98
|
end
|
114
|
-
|
115
99
|
end
|
116
100
|
|
117
101
|
describe Metar::Lightning do
|
118
|
-
|
119
102
|
context '.parse_chunks' do
|
120
|
-
|
121
103
|
[
|
122
104
|
['direction', 'LTG SE', [:default, nil, ['SE']]],
|
123
105
|
['distance direction', 'LTG DSNT SE', [:default, 16093.44, ['SE']]],
|
@@ -151,7 +133,7 @@ describe Metar::Lightning do
|
|
151
133
|
it 'fails if the first chunk is not LTGnnn' do
|
152
134
|
expect do
|
153
135
|
Metar::Lightning.parse_chunks(['FOO'])
|
154
|
-
end.
|
136
|
+
end.to raise_error(RuntimeError, /not lightning/)
|
155
137
|
end
|
156
138
|
|
157
139
|
it "doesn't not fail if all chunks are parsed" do
|
@@ -161,8 +143,5 @@ describe Metar::Lightning do
|
|
161
143
|
|
162
144
|
expect(chunks).to eq([])
|
163
145
|
end
|
164
|
-
|
165
146
|
end
|
166
|
-
|
167
147
|
end
|
168
|
-
|
@@ -6,10 +6,10 @@ describe Metar::Report do
|
|
6
6
|
let(:parser) do
|
7
7
|
double(
|
8
8
|
Metar::Parser,
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
9
|
+
station_code: station_code,
|
10
|
+
date: Date.parse(metar_date),
|
11
|
+
time: Time.parse(metar_datetime),
|
12
|
+
observer: :real
|
13
13
|
)
|
14
14
|
end
|
15
15
|
let(:station_code) { "SSSS" }
|
@@ -17,7 +17,9 @@ describe Metar::Report do
|
|
17
17
|
let(:metar_date) { "2008/05/06" }
|
18
18
|
let(:metar_time) { "10:56" }
|
19
19
|
let(:metar_datetime) { "#{metar_date} #{metar_time}" }
|
20
|
-
let(:station)
|
20
|
+
let(:station) do
|
21
|
+
double(Metar::Station, name: 'Airport 1', country: 'Wwwwww')
|
22
|
+
end
|
21
23
|
|
22
24
|
before do
|
23
25
|
allow(Metar::Station).to receive(:find_by_cccc).with(station_code) { station }
|
@@ -82,7 +84,7 @@ describe Metar::Report do
|
|
82
84
|
:temperature,
|
83
85
|
:dew_point,
|
84
86
|
:sea_level_pressure,
|
85
|
-
].each do |
|
87
|
+
].each do |attribute|
|
86
88
|
example attribute do
|
87
89
|
allow(parser).to receive(attribute) { attribute.to_s }
|
88
90
|
|
@@ -91,7 +93,7 @@ describe Metar::Report do
|
|
91
93
|
end
|
92
94
|
|
93
95
|
context "#sky_summary" do
|
94
|
-
let(:conditions1) { double(:
|
96
|
+
let(:conditions1) { double(to_summary: "skies1") }
|
95
97
|
|
96
98
|
it "returns the summary" do
|
97
99
|
allow(parser).to receive(:sky_conditions) { [conditions1] }
|
@@ -107,7 +109,7 @@ describe Metar::Report do
|
|
107
109
|
|
108
110
|
it "uses the last, if there is more than 1" do
|
109
111
|
@skies1 = double("sky_conditions1")
|
110
|
-
@skies2 = double("sky_conditions2", :
|
112
|
+
@skies2 = double("sky_conditions2", to_summary: "skies2")
|
111
113
|
allow(parser).to receive(:sky_conditions) { [@skies1, @skies2] }
|
112
114
|
|
113
115
|
expect(subject.sky_summary).to eq("skies2")
|
@@ -117,28 +119,28 @@ describe Metar::Report do
|
|
117
119
|
|
118
120
|
context "joined" do
|
119
121
|
it "#runway_visible_range" do
|
120
|
-
@rvr1 = double("rvr1", :
|
121
|
-
@rvr2 = double("rvr2", :
|
122
|
+
@rvr1 = double("rvr1", to_s: "rvr1")
|
123
|
+
@rvr2 = double("rvr2", to_s: "rvr2")
|
122
124
|
allow(parser).to receive(:runway_visible_range) { [@rvr1, @rvr2] }
|
123
125
|
|
124
126
|
expect(subject.runway_visible_range).to eq("rvr1, rvr2")
|
125
127
|
end
|
126
128
|
|
127
129
|
it "#present_weather" do
|
128
|
-
allow(parser).to receive(:present_weather) {
|
130
|
+
allow(parser).to receive(:present_weather) { %w(pw1 pw2) }
|
129
131
|
|
130
132
|
expect(subject.present_weather).to eq("pw1, pw2")
|
131
133
|
end
|
132
134
|
|
133
135
|
it "#remarks" do
|
134
|
-
allow(parser).to receive(:remarks) {
|
136
|
+
allow(parser).to receive(:remarks) { %w(rem1 rem2) }
|
135
137
|
|
136
138
|
expect(subject.remarks).to eq("rem1, rem2")
|
137
139
|
end
|
138
140
|
|
139
141
|
it '#sky_conditions' do
|
140
|
-
sky1 = double('sky1', :
|
141
|
-
sky2 = double('sky2', :
|
142
|
+
sky1 = double('sky1', to_s: 'sky1')
|
143
|
+
sky2 = double('sky2', to_s: 'sky2')
|
142
144
|
allow(parser).to receive(:sky_conditions) { [sky1, sky2] }
|
143
145
|
|
144
146
|
expect(subject.sky_conditions).to eq("sky1, sky2")
|
@@ -147,8 +149,8 @@ describe Metar::Report do
|
|
147
149
|
end
|
148
150
|
|
149
151
|
context '#to_s' do
|
150
|
-
let(:sky1) { double('sky1', :
|
151
|
-
let(:sky2) { double('sky2', :
|
152
|
+
let(:sky1) { double('sky1', to_summary: 'sky1') }
|
153
|
+
let(:sky2) { double('sky2', to_summary: 'sky2') }
|
152
154
|
|
153
155
|
before do
|
154
156
|
allow(parser).to receive(:wind) { "wind" }
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "spec_helper"
|
3
|
+
|
4
|
+
RSpec::Matchers.define :be_runway_visible_range do |designator, visibility1, visibility2, tendency|
|
5
|
+
match do |rvr|
|
6
|
+
if rvr.nil? && designator.nil?
|
7
|
+
true
|
8
|
+
elsif rvr.nil? != designator.nil?
|
9
|
+
false
|
10
|
+
elsif rvr.visibility1.nil? != visibility1.nil?
|
11
|
+
false
|
12
|
+
elsif rvr.visibility2.nil? != visibility2.nil?
|
13
|
+
false
|
14
|
+
elsif rvr.tendency.nil? != tendency.nil?
|
15
|
+
false
|
16
|
+
elsif ! visibility1.nil? &&
|
17
|
+
((rvr.visibility1.distance.value - visibility1[0]).abs > 0.01 ||
|
18
|
+
rvr.visibility1.comparator != visibility1[ 2 ])
|
19
|
+
false
|
20
|
+
elsif ! visibility2.nil? &&
|
21
|
+
((rvr.visibility2.distance.value - visibility2[0]).abs > 0.02 ||
|
22
|
+
rvr.visibility2.comparator != visibility2[2])
|
23
|
+
false
|
24
|
+
elsif tendency != rvr.tendency
|
25
|
+
false
|
26
|
+
else
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe Metar::RunwayVisibleRange do
|
33
|
+
context '.parse' do
|
34
|
+
[
|
35
|
+
['understands R + nn + / + nnnn', 'R12/3400', ['12', [3400.00, nil, nil], nil, nil]],
|
36
|
+
['understands runway positions: RLC', 'R12L/3400', ['12L', [3400.00, nil, nil], nil, nil]],
|
37
|
+
['understands comparators: PM', 'R12/P3400', ['12', [3400.00, nil, :more_than], nil, nil]],
|
38
|
+
['understands tendencies: NUD', 'R12/3400U', ['12', [3400.00, nil, nil], nil, :improving]],
|
39
|
+
['understands feet', 'R12/3400FT', ['12', [1036.32, nil, nil], nil, nil]],
|
40
|
+
['understands second visibilities (m)', 'R26/0750V1200U', ['12', [ 750.0, nil, nil], [1200.0, nil, nil], :improving]],
|
41
|
+
['understands second visibilities (ft)', 'R12/3400V1800FT', ['12', [1036.32, nil, nil], [548.64, nil, nil], nil]],
|
42
|
+
['returns nil for nil', nil, [nil, nil, nil, nil]],
|
43
|
+
].each do |docstring, raw, expected|
|
44
|
+
example docstring do
|
45
|
+
expect(Metar::RunwayVisibleRange.parse(raw)).to be_runway_visible_range(*expected)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context '#to_s' do
|
51
|
+
before :all do
|
52
|
+
@locale = I18n.locale
|
53
|
+
I18n.locale = :it
|
54
|
+
end
|
55
|
+
|
56
|
+
after :all do
|
57
|
+
I18n.locale = @locale
|
58
|
+
end
|
59
|
+
|
60
|
+
[
|
61
|
+
['v1', :en, [[3400.00, nil, nil], nil, nil], 'runway 14: 3400m'],
|
62
|
+
['v1 and v2', :en, [[3400.00, nil, nil], [1900.00, nil, nil], nil ], 'runway 14: from 3400m to 1900m'],
|
63
|
+
['v1 and tendency', :en, [[3400.00, nil, nil], nil, :improving ], 'runway 14: 3400m improving'],
|
64
|
+
].each do |docstring, locale, (visibility1, visibility2, tendency), expected|
|
65
|
+
d1 = Metar::Distance.new(visibility1[0])
|
66
|
+
v1 = Metar::Visibility.new(d1, visibility1[1], visibility1[2])
|
67
|
+
v2 =
|
68
|
+
if ! visibility2.nil?
|
69
|
+
d2 = Metar::Distance.new(visibility2[0])
|
70
|
+
Metar::Visibility.new(d2, visibility2[1], visibility2[2])
|
71
|
+
else
|
72
|
+
nil
|
73
|
+
end
|
74
|
+
|
75
|
+
example docstring + " (#{locale})" do
|
76
|
+
I18n.locale = locale
|
77
|
+
expect(Metar::RunwayVisibleRange.new('14', v1, v2, tendency).to_s).to eq(expected)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -9,7 +9,7 @@ if RUBY_VERSION > '1.9'
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
require File.expand_path(
|
12
|
+
require File.expand_path(File.dirname(__FILE__) + '/../lib/metar')
|
13
13
|
|
14
14
|
RSpec::Matchers.define :be_temperature_extreme do |extreme, value|
|
15
15
|
match do |remark|
|
data/spec/speed_spec.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Metar::Speed do
|
4
|
+
context '.parse' do
|
5
|
+
it 'returns nil for nil' do
|
6
|
+
speed = Metar::Speed.parse(nil)
|
7
|
+
|
8
|
+
expect(speed).to be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'parses knots' do
|
12
|
+
speed = Metar::Speed.parse('5KT')
|
13
|
+
|
14
|
+
expect(speed).to be_a(Metar::Speed)
|
15
|
+
expect(speed.value).to be_within(0.01).of(2.57)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'parses meters per second' do
|
19
|
+
speed = Metar::Speed.parse('7MPS')
|
20
|
+
|
21
|
+
expect(speed).to be_a(Metar::Speed)
|
22
|
+
expect(speed.value).to be_within(0.01).of(7.00)
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'parses kilometers per hour' do
|
26
|
+
speed = Metar::Speed.parse('14KMH')
|
27
|
+
|
28
|
+
expect(speed).to be_a(Metar::Speed)
|
29
|
+
expect(speed.value).to be_within(0.01).of(3.89)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'trates straight numbers as kilomters per hour' do
|
33
|
+
speed = Metar::Speed.parse('14')
|
34
|
+
|
35
|
+
expect(speed).to be_a(Metar::Speed)
|
36
|
+
expect(speed.value).to be_within(0.01).of(3.89)
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'returns nil for other strings' do
|
40
|
+
speed = Metar::Speed.parse('')
|
41
|
+
|
42
|
+
expect(speed).to be_nil
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -4,10 +4,10 @@ require "spec_helper"
|
|
4
4
|
require "stringio"
|
5
5
|
|
6
6
|
RSpec::Matchers.define :have_attribute do |attribute|
|
7
|
-
match do |
|
8
|
-
if !
|
7
|
+
match do |object|
|
8
|
+
if !object.respond_to?(attribute)
|
9
9
|
false
|
10
|
-
elsif object.method(
|
10
|
+
elsif object.method(attribute).arity != 0
|
11
11
|
false
|
12
12
|
else
|
13
13
|
true
|
@@ -16,11 +16,10 @@ RSpec::Matchers.define :have_attribute do |attribute|
|
|
16
16
|
end
|
17
17
|
|
18
18
|
describe Metar::Station do
|
19
|
-
let(:file) { double(File) }
|
20
|
-
|
21
19
|
context "using structures" do
|
22
20
|
before do
|
23
|
-
allow(Metar::Station).to receive(:open)
|
21
|
+
allow(Metar::Station).to receive(:open)
|
22
|
+
.with(Metar::Station::NOAA_STATION_LIST_URL) { nsd_file }
|
24
23
|
end
|
25
24
|
|
26
25
|
context ".countries" do
|
@@ -69,18 +68,36 @@ describe Metar::Station do
|
|
69
68
|
end
|
70
69
|
end
|
71
70
|
|
71
|
+
##
|
72
|
+
# NOAA Station list fields:
|
73
|
+
#
|
74
|
+
# 0 1 2 3 45 6 7 8 9 10 11 12 13
|
75
|
+
# PPPP;00;000;Airport P1;;Ppppp;1;11-03S;055-24E;11-03S;055-24E;000;000;P\r
|
76
|
+
#
|
77
|
+
# 0 - CCCC
|
78
|
+
# 1 - ?
|
79
|
+
# 2 - ?
|
80
|
+
# 3 - name of station
|
81
|
+
# 4 - state
|
82
|
+
# 5 - country
|
83
|
+
# 6 - ?
|
84
|
+
# 7 - latitude1
|
85
|
+
# 8 - longitude1
|
86
|
+
# 9 - latitude2
|
87
|
+
# 10 - longitude2
|
88
|
+
# 11 - ?
|
89
|
+
# 12 - ?
|
90
|
+
# 13 - ?
|
91
|
+
#
|
72
92
|
def nsd_file
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
EOT
|
81
|
-
StringIO.new( nsd_text )
|
93
|
+
nsd_text = <<-EOT.gsub(/^\s{8}/, "")
|
94
|
+
PPPP;00;000;Airport P1;;Ppppp;1;11-03S;055-24E;11-03S;055-24E;000;000;P\r
|
95
|
+
AAAA;00;000;Airport A1;;Aaaaa;1;11-03S;055-24E;11-03S;055-24E;000;000;P\r
|
96
|
+
AAAB;00;000;Airport A2;;Aaaaa;1;11-03S;055-24E;11-03S;055-24E;000;000;P\r
|
97
|
+
BBBA;00;000;Airport B1;;Bbbbb;1;11-03S;055-24E;11-03S;055-24E;000;000;P\r
|
98
|
+
EOT
|
99
|
+
StringIO.new(nsd_text)
|
82
100
|
end
|
83
|
-
|
84
101
|
end
|
85
102
|
|
86
103
|
context ".to_longitude" do
|
@@ -103,58 +120,72 @@ EOT
|
|
103
120
|
end
|
104
121
|
end
|
105
122
|
|
106
|
-
|
123
|
+
let(:cccc) { "DDDD" }
|
124
|
+
let(:name) { "Station name" }
|
125
|
+
let(:state) { "State" }
|
126
|
+
let(:country) { "Country" }
|
127
|
+
let(:noaa_raw) do
|
128
|
+
cccc +
|
129
|
+
";00;000;" +
|
130
|
+
name + ";" +
|
131
|
+
state + ";" +
|
132
|
+
country + ";1;11-03S;055-24E;11-03S;055-24E;000;000;P"
|
133
|
+
end
|
134
|
+
let(:noaa_data) do
|
107
135
|
{
|
108
|
-
:cccc
|
109
|
-
:
|
110
|
-
:state
|
111
|
-
:country
|
112
|
-
:
|
113
|
-
:
|
114
|
-
:
|
136
|
+
cccc: cccc,
|
137
|
+
name: name,
|
138
|
+
state: state,
|
139
|
+
country: country,
|
140
|
+
longitude: "055-24E",
|
141
|
+
latitude: "11-03S",
|
142
|
+
raw: noaa_raw,
|
115
143
|
}
|
116
144
|
end
|
117
145
|
|
118
146
|
context "attributes" do
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
147
|
+
subject { Metar::Station.new("DDDD", noaa_data) }
|
148
|
+
it { should have_attribute(:cccc) }
|
149
|
+
it { should have_attribute(:code) }
|
150
|
+
it { should have_attribute(:name) }
|
151
|
+
it { should have_attribute(:state) }
|
152
|
+
it { should have_attribute(:country) }
|
153
|
+
it { should have_attribute(:longitude) }
|
154
|
+
it { should have_attribute(:latitude) }
|
155
|
+
it { should have_attribute(:raw) }
|
128
156
|
end
|
129
|
-
|
157
|
+
|
130
158
|
context "initialization" do
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
159
|
+
it "should fail if cccc is missing" do
|
160
|
+
expect do
|
161
|
+
Metar::Station.new(nil, {})
|
162
|
+
end.to raise_error(RuntimeError, /must not be nil/)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should fail if cccc is empty" do
|
166
|
+
expect do
|
167
|
+
Metar::Station.new("", {})
|
168
|
+
end.to raise_error(RuntimeError, /must not be empty/)
|
169
|
+
end
|
170
|
+
|
143
171
|
context "with noaa data" do
|
144
172
|
subject { Metar::Station.new("DDDD", noaa_data) }
|
145
173
|
|
146
|
-
specify { expect(subject.cccc).to eq(
|
147
|
-
specify { expect(subject.name).to eq(
|
148
|
-
specify { expect(subject.state).to eq(
|
149
|
-
specify { expect(subject.country).to eq(
|
174
|
+
specify { expect(subject.cccc).to eq(cccc) }
|
175
|
+
specify { expect(subject.name).to eq(name) }
|
176
|
+
specify { expect(subject.state).to eq(state) }
|
177
|
+
specify { expect(subject.country).to eq(country) }
|
150
178
|
specify { expect(subject.longitude).to eq(55.4) }
|
151
179
|
specify { expect(subject.latitude).to eq(-11.05) }
|
152
|
-
specify { expect(subject.raw).to eq(
|
180
|
+
specify { expect(subject.raw).to eq(noaa_raw) }
|
153
181
|
end
|
154
182
|
end
|
155
183
|
|
156
184
|
context "object navigation" do
|
157
|
-
let(:
|
185
|
+
let(:metar) do
|
186
|
+
"PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910"
|
187
|
+
end
|
188
|
+
let(:raw) { double(Metar::Raw, metar: metar, time: "2010/02/06 16:10") }
|
158
189
|
|
159
190
|
before do
|
160
191
|
# TODO: hack - once parser returns station this can be removed
|