metar-parser 1.2.1 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
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