metar-parser 1.2.1 → 1.3.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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/lib/metar/data/base.rb +15 -0
  3. data/lib/metar/data/density_altitude.rb +15 -0
  4. data/lib/metar/data/direction.rb +9 -0
  5. data/lib/metar/data/distance.rb +27 -0
  6. data/lib/metar/data/lightning.rb +61 -0
  7. data/lib/metar/data/observer.rb +24 -0
  8. data/lib/metar/data/pressure.rb +23 -0
  9. data/lib/metar/data/remark.rb +98 -0
  10. data/lib/metar/data/runway_visible_range.rb +85 -0
  11. data/lib/metar/data/sky_condition.rb +61 -0
  12. data/lib/metar/data/speed.rb +22 -0
  13. data/lib/metar/data/station_code.rb +7 -0
  14. data/lib/metar/data/temperature.rb +21 -0
  15. data/lib/metar/data/temperature_and_dew_point.rb +18 -0
  16. data/lib/metar/data/time.rb +54 -0
  17. data/lib/metar/data/variable_wind.rb +25 -0
  18. data/lib/metar/data/vertical_visibility.rb +26 -0
  19. data/lib/metar/data/visibility.rb +71 -0
  20. data/lib/metar/data/visibility_remark.rb +8 -0
  21. data/lib/metar/data/weather_phenomenon.rb +86 -0
  22. data/lib/metar/data/wind.rb +82 -0
  23. data/lib/metar/data.rb +22 -636
  24. data/lib/metar/i18n.rb +6 -0
  25. data/lib/metar/parser.rb +165 -120
  26. data/lib/metar/report.rb +1 -1
  27. data/lib/metar/version.rb +2 -2
  28. data/lib/metar.rb +7 -6
  29. data/locales/de.yml +1 -0
  30. data/locales/en.yml +1 -0
  31. data/locales/it.yml +2 -1
  32. data/locales/pt-BR.yml +1 -0
  33. data/spec/data/density_altitude_spec.rb +12 -0
  34. data/spec/{distance_spec.rb → data/distance_spec.rb} +1 -1
  35. data/spec/data/lightning_spec.rb +49 -0
  36. data/spec/data/pressure_spec.rb +22 -0
  37. data/spec/data/remark_spec.rb +99 -0
  38. data/spec/data/runway_visible_range_spec.rb +92 -0
  39. data/spec/{sky_condition_spec.rb → data/sky_condition_spec.rb} +10 -6
  40. data/spec/data/speed_spec.rb +45 -0
  41. data/spec/data/temperature_spec.rb +36 -0
  42. data/spec/{variable_wind_spec.rb → data/variable_wind_spec.rb} +6 -6
  43. data/spec/{vertical_visibility_spec.rb → data/vertical_visibility_spec.rb} +2 -2
  44. data/spec/{data_spec.rb → data/visibility_remark_spec.rb} +1 -11
  45. data/spec/{visibility_spec.rb → data/visibility_spec.rb} +9 -7
  46. data/spec/{weather_phenomenon_spec.rb → data/weather_phenomenon_spec.rb} +7 -3
  47. data/spec/{wind_spec.rb → data/wind_spec.rb} +10 -7
  48. data/spec/parser_spec.rb +107 -13
  49. data/spec/report_spec.rb +12 -1
  50. data/spec/spec_helper.rb +1 -1
  51. data/spec/station_spec.rb +2 -1
  52. metadata +56 -31
  53. data/spec/pressure_spec.rb +0 -22
  54. data/spec/remark_spec.rb +0 -147
  55. data/spec/runway_visible_range_spec.rb +0 -81
  56. data/spec/speed_spec.rb +0 -45
  57. data/spec/temperature_spec.rb +0 -36
data/lib/metar/parser.rb CHANGED
@@ -1,4 +1,6 @@
1
- require File.join(File.dirname(__FILE__), 'data')
1
+ require "m9t"
2
+
3
+ require "metar/data"
2
4
 
3
5
  # References:
4
6
  # WMO = World Meteorological Organization Manual on Codes Volume I.1
@@ -26,11 +28,22 @@ module Metar
26
28
  thread_attributes[:compliance] = compliance
27
29
  end
28
30
 
29
- attr_reader :raw, :metar
30
- attr_reader :station_code, :observer, :wind, :variable_wind, :visibility,
31
- :minimum_visibility, :runway_visible_range, :present_weather, :sky_conditions,
32
- :vertical_visibility, :temperature, :dew_point, :sea_level_pressure,
33
- :recent_weather, :unparsed, :remarks
31
+ attr_reader :raw
32
+ attr_reader :metar
33
+ attr_reader :observer
34
+ attr_reader :wind
35
+ attr_reader :variable_wind
36
+ attr_reader :visibility
37
+ attr_reader :minimum_visibility
38
+ attr_reader :runway_visible_range
39
+ attr_reader :present_weather
40
+ attr_reader :sky_conditions
41
+ attr_reader :vertical_visibility
42
+ attr_reader :temperature_and_dew_point
43
+ attr_reader :sea_level_pressure
44
+ attr_reader :recent_weather
45
+ attr_reader :unparsed
46
+ attr_reader :remarks
34
47
 
35
48
  def initialize(raw)
36
49
  @raw = raw
@@ -38,39 +51,101 @@ module Metar
38
51
  analyze
39
52
  end
40
53
 
54
+ def station_code
55
+ @station_code.value
56
+ end
57
+
41
58
  def time
42
- Time.gm(@raw.time.year, @raw.time.month, @day, @hour, @minute)
59
+ @time.value
60
+ end
61
+
62
+ def cavok?
63
+ @cavok
64
+ end
65
+
66
+ def temperature
67
+ return nil if @temperature_and_dew_point.nil?
68
+ @temperature_and_dew_point.temperature
69
+ end
70
+
71
+ def dew_point
72
+ return nil if @temperature_and_dew_point.nil?
73
+ @temperature_and_dew_point.dew_point
74
+ end
75
+
76
+ def raw_attributes
77
+ attr = {
78
+ metar: metar,
79
+ datetime: @time.raw,
80
+ station_code: station_code,
81
+ }
82
+ %i(
83
+ minimum_visibility
84
+ observer
85
+ sea_level_pressure
86
+ temperature_and_dew_point
87
+ visibility variable_wind vertical_visibility
88
+ wind
89
+ ).each do |key|
90
+ attr = add_raw_if_present(attr, key)
91
+ end
92
+ %i(
93
+ present_weather
94
+ recent_weather remarks runway_visible_range
95
+ sky_conditions
96
+ ).each do |key|
97
+ attr = add_raw_if_not_empty(attr, key)
98
+ end
99
+ attr[:cavok] = "CAVOK" if cavok?
100
+ attr
43
101
  end
44
102
 
45
103
  private
46
104
 
105
+ def add_raw_if_present(hash, attribute)
106
+ value = send(attribute)
107
+ return hash if value.nil?
108
+ return hash if value.raw.nil?
109
+ hash[attribute] = value.raw
110
+ hash
111
+ end
112
+
113
+ def add_raw_if_not_empty(hash, attribute)
114
+ values = send(attribute)
115
+ raws = values.map(&:raw).compact
116
+ return hash if raws.size == 0
117
+ hash[attribute] = raws.join(" ")
118
+ hash
119
+ end
120
+
47
121
  def analyze
48
122
  @chunks = @metar.split(' ')
49
123
 
50
124
  @station_code = nil
51
- @observer = :real
125
+ @time = nil
126
+ @observer = nil
52
127
  @wind = nil
53
128
  @variable_wind = nil
129
+ @cavok = nil
54
130
  @visibility = nil
55
131
  @minimum_visibility = nil
56
132
  @runway_visible_range = []
57
133
  @present_weather = []
58
134
  @sky_conditions = []
59
135
  @vertical_visibility = nil
60
- @temperature = nil
61
- @dew_point = nil
136
+ @temperature_and_dew_point = nil
62
137
  @sea_level_pressure = nil
63
138
  @recent_weather = []
64
139
  @unparsed = []
65
140
  @remarks = []
66
141
 
67
- seek_location
142
+ seek_station_code
68
143
  seek_datetime
69
- seek_cor_auto
144
+ seek_observer
70
145
  seek_wind
71
146
  seek_variable_wind
72
- cavok = seek_cavok
73
- if not cavok
147
+ seek_cavok
148
+ if !cavok?
74
149
  seek_visibility
75
150
  seek_minimum_visibility
76
151
  seek_runway_visible_range
@@ -85,92 +160,64 @@ module Metar
85
160
  seek_remarks
86
161
  end
87
162
 
88
- def seek_location
89
- if @chunks[0] =~ /^[A-Z][A-Z0-9]{3}$/
90
- @station_code = @chunks.shift
91
- else
163
+ def seek_station_code
164
+ @station_code = Metar::Data::StationCode.parse(@chunks[0])
165
+ if @station_code.nil?
92
166
  raise ParseError.new("Expecting location, found '#{ @chunks[0] }' in #{@metar}")
93
167
  end
168
+ @chunks.shift
169
+ @station_code
94
170
  end
95
171
 
96
172
  def seek_datetime
97
- found = false
98
- date_matcher =
99
- if strict?
100
- /^(\d{2})(\d{2})(\d{2})Z$/
101
- else
102
- /^(\d{1,2})(\d{2})(\d{2})Z$/
103
- end
104
- if @chunks[0] =~ date_matcher
105
- @day, @hour, @minute = $1.to_i, $2.to_i, $3.to_i
106
- found = true
107
- else
108
- if not strict?
109
- if @chunks[0] =~ /^(\d{1,2})(\d{2})Z$/
110
- # The day is missing, use today's date
111
- @day = Time.now.day
112
- @hour, @minute = $1.to_i, $2.to_i, $3.to_i
113
- found = true
114
- end
115
- end
116
- end
117
- if found
118
- @chunks.shift
119
- else
120
- raise ParseError.new("Expecting datetime, found '#{@chunks[0]}' in #{@metar}")
173
+ datetime = @chunks.shift
174
+ @time = Metar::Data::Time.parse(
175
+ datetime, year: raw.time.year, month: raw.time.month, strict: strict?
176
+ )
177
+ if !@time
178
+ raise ParseError.new("Expecting datetime, found '#{datetime}' in #{@metar}")
121
179
  end
180
+ @time
122
181
  end
123
182
 
124
- def seek_cor_auto
125
- case
126
- when @chunks[0] == 'AUTO' # WMO 15.4
127
- @chunks.shift
128
- @observer = :auto
129
- when @chunks[0] == 'COR' # WMO specified code word for correction
130
- @chunks.shift
131
- @observer = :corrected
132
- when @chunks[0] =~ /CC[A-Z]/ # Canadian correction
133
- # Canada uses CCA for first correction, CCB for second, etc...
134
- @chunks.shift
135
- @observer = :corrected
136
- when @chunks[0] == 'RTD' # Delayed observation, no comments on observer
137
- @chunks.shift
138
- else
139
- nil
140
- end
183
+ def seek_observer
184
+ @observer = Metar::Data::Observer.parse(@chunks[0])
185
+ @chunks.shift if @observer.raw
186
+ @observer
141
187
  end
142
188
 
143
189
  def seek_wind
144
- wind = Wind.parse(@chunks[0])
145
- if wind
146
- @chunks.shift
147
- @wind = wind
148
- end
190
+ @wind = Metar::Data::Wind.parse(@chunks[0])
191
+ @chunks.shift if @wind
192
+ @wind
149
193
  end
150
194
 
151
195
  def seek_variable_wind
152
- variable_wind = VariableWind.parse(@chunks[0])
153
- if variable_wind
154
- @chunks.shift
155
- @variable_wind = variable_wind
156
- end
196
+ @variable_wind = Metar::Data::VariableWind.parse(@chunks[0])
197
+ @chunks.shift if @variable_wind
198
+ @variable_wind
157
199
  end
158
200
 
159
201
  def seek_cavok
160
202
  if @chunks[0] == 'CAVOK'
203
+ @visibility = Metar::Data::Visibility.new(
204
+ nil,
205
+ distance: M9t::Distance.kilometers(10), comparator: :more_than
206
+ )
207
+ @present_weather << Metar::Data::WeatherPhenomenon.new(
208
+ nil, phenomenon: "No significant weather"
209
+ )
210
+ @sky_conditions << Metar::Data::SkyCondition.new(nil) # = 'clear skies'
161
211
  @chunks.shift
162
- @visibility = Visibility.new(M9t::Distance.kilometers(10), nil, :more_than)
163
- @present_weather << Metar::WeatherPhenomenon.new('No significant weather')
164
- @sky_conditions << SkyCondition.new # = 'clear skies'
165
- return true
212
+ @cavok = true
166
213
  else
167
- return false
214
+ @cavok = false
168
215
  end
169
216
  end
170
217
 
171
218
  # 15.10, 15.6.1
172
219
  def seek_visibility
173
- if @observer == :auto # WMO 15.4
220
+ if observer.value == :auto # WMO 15.4
174
221
  if @chunks[0] == '////'
175
222
  @chunks.shift # Simply dispose of it
176
223
  return
@@ -178,50 +225,52 @@ module Metar
178
225
  end
179
226
 
180
227
  if @chunks[0] == '1' or @chunks[0] == '2'
181
- visibility = Visibility.parse(@chunks[0] + ' ' + @chunks[1])
182
- if visibility
228
+ @visibility = Metar::Data::Visibility.parse(@chunks[0] + ' ' + @chunks[1])
229
+ if @visibility
183
230
  @chunks.shift
184
231
  @chunks.shift
185
- @visibility = visibility
186
232
  end
187
233
  else
188
- visibility = Visibility.parse(@chunks[0])
189
- if visibility
234
+ @visibility = Metar::Data::Visibility.parse(@chunks[0])
235
+ if @visibility
190
236
  @chunks.shift
191
- @visibility = visibility
192
237
  end
193
238
  end
239
+ @visibility
194
240
  end
195
241
 
196
242
  # Optional after visibility: 15.6.2
197
243
  def seek_minimum_visibility
198
- minimum_visibility = Visibility.parse(@chunks[0])
199
- if minimum_visibility
200
- @chunks.shift
201
- @minimum_visibility = minimum_visibility
202
- end
244
+ @minimum_visibility = Metar::Data::Visibility.parse(@chunks[0])
245
+ @chunks.shift if @minimum_visibility
246
+ @minimum_visibility
203
247
  end
204
248
 
205
249
  def seek_runway_visible_range
206
250
  loop do
207
- runway_visible_range = RunwayVisibleRange.parse(@chunks[0])
208
- break if runway_visible_range.nil?
251
+ rvr = Metar::Data::RunwayVisibleRange.parse(@chunks[0])
252
+ break if rvr.nil?
209
253
  @chunks.shift
210
- @runway_visible_range << runway_visible_range
254
+ @runway_visible_range << rvr
211
255
  end
256
+ @runway_visible_range
212
257
  end
213
258
 
214
259
  def seek_present_weather
215
- if @observer == :auto
260
+ if observer.value == :auto
216
261
  if @chunks[0] == '//' # WMO 15.4
217
- @chunks.shift # Simply dispose of it
218
- @present_weather << Metar::WeatherPhenomenon.new('not observed')
262
+ @present_weather << Metar::Data::WeatherPhenomenon.new(
263
+ nil, phenomenon: "not observed"
264
+ )
265
+ @chunks.shift
219
266
  return
220
267
  end
221
268
  end
222
269
 
223
270
  loop do
224
- wtp = WeatherPhenomenon.parse(@chunks[0])
271
+ break if @chunks.size == 0
272
+ break if @chunks[0].start_with?("RE")
273
+ wtp = Metar::Data::WeatherPhenomenon.parse(@chunks[0])
225
274
  break if wtp.nil?
226
275
  @chunks.shift
227
276
  @present_weather << wtp
@@ -230,7 +279,7 @@ module Metar
230
279
 
231
280
  # Repeatable: 15.9.1.3
232
281
  def seek_sky_conditions
233
- if @observer == :auto # WMO 15.4
282
+ if observer.value == :auto # WMO 15.4
234
283
  if @chunks[0] == '///' or @chunks[0] == '//////'
235
284
  @chunks.shift # Simply dispose of it
236
285
  return
@@ -238,7 +287,7 @@ module Metar
238
287
  end
239
288
 
240
289
  loop do
241
- sky_condition = SkyCondition.parse(@chunks[0])
290
+ sky_condition = Metar::Data::SkyCondition.parse(@chunks[0])
242
291
  break if sky_condition.nil?
243
292
  @chunks.shift
244
293
  @sky_conditions << sky_condition
@@ -246,40 +295,36 @@ module Metar
246
295
  end
247
296
 
248
297
  def seek_vertical_visibility
249
- vertical_visibility = VerticalVisibility.parse(@chunks[0])
250
- if vertical_visibility
251
- @chunks.shift
252
- @vertical_visibility = vertical_visibility
253
- end
298
+ @vertical_visibility = Metar::Data::VerticalVisibility.parse(@chunks[0])
299
+ @chunks.shift if vertical_visibility
300
+ @vertical_visibility
254
301
  end
255
302
 
256
303
  def seek_temperature_dew_point
257
- case
258
- when @chunks[0] =~ /^(M?\d+|XX|\/\/)\/(M?\d+|XX|\/\/)?$/
259
- @chunks.shift
260
- @temperature = Metar::Temperature.parse($1)
261
- @dew_point = Metar::Temperature.parse($2)
262
- end
304
+ @temperature_and_dew_point = Metar::Data::TemperatureAndDewPoint.parse(
305
+ @chunks[0]
306
+ )
307
+
308
+ @chunks.shift if @temperature_and_dew_point
309
+ @temperature_and_dew_point
263
310
  end
264
311
 
265
312
  def seek_sea_level_pressure
266
- sea_level_pressure = Pressure.parse(@chunks[0])
267
- if sea_level_pressure
268
- @chunks.shift
269
- @sea_level_pressure = sea_level_pressure
270
- end
313
+ @sea_level_pressure = Metar::Data::Pressure.parse(@chunks[0])
314
+ @chunks.shift if @sea_level_pressure
315
+ @sea_level_pressure
271
316
  end
272
317
 
273
318
  def seek_recent_weather
274
319
  loop do
275
320
  return if @chunks.size == 0
276
- m = /^RE/.match(@chunks[0])
277
- break if m.nil?
278
- recent_weather = Metar::WeatherPhenomenon.parse(m.post_match)
321
+ break if !@chunks[0].start_with?("RE")
322
+ recent_weather = Metar::Data::WeatherPhenomenon.parse(@chunks[0])
279
323
  break if recent_weather.nil?
280
324
  @chunks.shift
281
325
  @recent_weather << recent_weather
282
326
  end
327
+ @recent_weather
283
328
  end
284
329
 
285
330
  def seek_to_remarks
@@ -297,13 +342,13 @@ module Metar
297
342
  # WMO: 15.15
298
343
  def seek_remarks
299
344
  return if @chunks.size == 0
300
- raise 'seek_remarks calls without remark' if @chunks[0] != 'RMK'
345
+ raise 'seek_remarks called without remark' if @chunks[0] != 'RMK'
301
346
 
302
347
  @chunks.shift # Drop 'RMK'
303
348
  @remarks = []
304
349
  loop do
305
350
  break if @chunks.size == 0
306
- r = Metar::Remark.parse(@chunks[0])
351
+ r = Metar::Data::Remark.parse(@chunks[0])
307
352
  if r
308
353
  if r.is_a?(Array)
309
354
  @remarks += r
@@ -315,17 +360,17 @@ module Metar
315
360
  end
316
361
  if @chunks[0] == 'VIS' and @chunks.size >= 3 and @chunks[1] == 'MIN'
317
362
  @chunks.shift(2)
318
- r = Metar::VisibilityRemark.parse(@chunks[0])
363
+ r = Metar::Data::VisibilityRemark.parse(@chunks[0])
319
364
  @remarks << r
320
365
  end
321
- if @chunks[0] == 'DENSITY' and @chunks.size >= 3 and @chunks[1] == 'ALT'
366
+ if @chunks[0] == 'DENSITY' && @chunks.size >= 3 && @chunks[1] == 'ALT'
322
367
  @chunks.shift(2)
323
- r = Metar::DensityAltitude.parse(@chunks[0])
368
+ r = Metar::Data::DensityAltitude.parse(@chunks[0])
324
369
  @remarks << r
325
370
  end
326
371
  case
327
372
  when @chunks[0] =~ /^LTG(|CG|IC|CC|CA)$/
328
- r = Metar::Lightning.parse_chunks(@chunks)
373
+ r = Metar::Data::Lightning.parse_chunks(@chunks)
329
374
  @remarks << r
330
375
  else
331
376
  @remarks << @chunks.shift
data/lib/metar/report.rb CHANGED
@@ -91,7 +91,7 @@ module Metar
91
91
  end
92
92
 
93
93
  def sea_level_pressure
94
- @parser.sea_level_pressure.to_s
94
+ @parser.sea_level_pressure.value.to_s
95
95
  end
96
96
 
97
97
  def remarks
data/lib/metar/version.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  module Metar
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
- MINOR = 2
5
- TINY = 1
4
+ MINOR = 3
5
+ TINY = 0
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
data/lib/metar.rb CHANGED
@@ -1,11 +1,11 @@
1
- require 'metar/raw'
2
- require 'metar/station'
3
- require 'metar/parser'
4
- require 'metar/report'
5
- require 'metar/version'
1
+ require "metar/i18n"
2
+ require "metar/raw"
3
+ require "metar/station"
4
+ require "metar/parser"
5
+ require "metar/report"
6
+ require "metar/version"
6
7
 
7
8
  module Metar
8
-
9
9
  # Base class for all Metar exceptions
10
10
  class MetarError < StandardError
11
11
  end
@@ -14,5 +14,6 @@ module Metar
14
14
  class ParseError < MetarError
15
15
  end
16
16
 
17
+ autoload :Data, "metar/data"
17
18
  end
18
19
 
data/locales/de.yml CHANGED
@@ -28,6 +28,7 @@ de:
28
28
  real: real
29
29
  auto: automatisch
30
30
  corrected: korrigiert
31
+ rtd: ""
31
32
  altitude:
32
33
  at: at
33
34
  distance:
data/locales/en.yml CHANGED
@@ -28,6 +28,7 @@ en:
28
28
  real: real
29
29
  auto: automatic
30
30
  corrected: corrected
31
+ rtd: ""
31
32
  altitude:
32
33
  at: at
33
34
  distance:
data/locales/it.yml CHANGED
@@ -26,8 +26,9 @@ it:
26
26
  observer:
27
27
  title: osservatore
28
28
  real: reale
29
- auto: automazzato
29
+ auto: automatizzato
30
30
  corrected: corretto
31
+ rtd: ""
31
32
  altitude:
32
33
  at: a
33
34
  distance:
data/locales/pt-BR.yml CHANGED
@@ -47,6 +47,7 @@ pt-BR:
47
47
  real: real
48
48
  auto: automático
49
49
  corrected: corrigido
50
+ rtd: ""
50
51
  altitude:
51
52
  at: a
52
53
  distance:
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ RSpec.describe Metar::Data::DensityAltitude do
5
+ describe ".parse" do
6
+ subject { described_class.parse("50FT") }
7
+
8
+ it "interprets the value as feet" do
9
+ expect(subject.height.to_feet).to eq(50)
10
+ end
11
+ end
12
+ end
@@ -1,7 +1,7 @@
1
1
  # encoding: utf-8
2
2
  require "spec_helper"
3
3
 
4
- describe Metar::Distance do
4
+ describe Metar::Data::Distance do
5
5
  let(:value) { 12_345.6789 }
6
6
 
7
7
  subject { described_class.new(value) }
@@ -0,0 +1,49 @@
1
+ require "spec_helper"
2
+
3
+ describe Metar::Data::Lightning do
4
+ context '.parse_chunks' do
5
+ [
6
+ ['direction', 'LTG SE', [:default, nil, ['SE']]],
7
+ ['distance direction', 'LTG DSNT SE', [:default, 16093.44, ['SE']]],
8
+ ['distance direction and direction', 'LTG DSNT NE AND W', [:default, 16093.44, ['NE', 'W']]],
9
+ ['distance direction-direction', 'LTG DSNT SE-SW', [:default, 16093.44, ['SE', 'SW']]],
10
+ ['distance all quandrants', 'LTG DSNT ALQDS', [:default, 16093.44, ['N', 'E', 'S', 'W']]],
11
+ ].each do |docstring, section, expected|
12
+ example docstring do
13
+ chunks = section.split(' ')
14
+ r = described_class.parse_chunks(chunks)
15
+
16
+ expect(r).to be_a(described_class)
17
+ expect(r.type).to eq(expected[0])
18
+ if expected[1]
19
+ expect(r.distance.value).to eq(expected[1])
20
+ else
21
+ expect(r.distance).to be_nil
22
+ end
23
+ expect(r.directions).to eq(expected[2])
24
+ end
25
+ end
26
+
27
+ it 'removes parsed chunks' do
28
+ chunks = ['LTG', 'DSNT', 'SE', 'FOO']
29
+
30
+ r = described_class.parse_chunks(chunks)
31
+
32
+ expect(chunks).to eq(['FOO'])
33
+ end
34
+
35
+ it 'fails if the first chunk is not LTGnnn' do
36
+ expect do
37
+ described_class.parse_chunks(['FOO'])
38
+ end.to raise_error(RuntimeError, /not lightning/)
39
+ end
40
+
41
+ it "doesn't not fail if all chunks are parsed" do
42
+ chunks = ['LTG', 'DSNT', 'SE']
43
+
44
+ r = described_class.parse_chunks(chunks)
45
+
46
+ expect(chunks).to eq([])
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,22 @@
1
+ require "spec_helper"
2
+
3
+ describe Metar::Data::Pressure do
4
+ context '.parse' do
5
+ it 'interprets the Q prefix as hectopascals' do
6
+ expect(described_class.parse('Q1300').value).to be_within(0.01).of(1.3)
7
+ end
8
+
9
+ it 'interprets the A prefix as inches of mercury' do
10
+ expect(described_class.parse('A1234').value).to be_within(0.01).of(0.42)
11
+ end
12
+
13
+ it 'require 4 digits' do
14
+ expect(described_class.parse('Q12345')).to be_nil
15
+ expect(described_class.parse('A123')).to be_nil
16
+ end
17
+
18
+ it 'returns nil for nil' do
19
+ expect(described_class.parse(nil)).to be_nil
20
+ end
21
+ end
22
+ end