metar-parser 1.1.4 → 1.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/lib/metar/data.rb CHANGED
@@ -4,14 +4,13 @@ require 'm9t'
4
4
 
5
5
  module Metar
6
6
  locales_path = File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'locales'))
7
- I18n.load_path += Dir.glob("#{ locales_path }/*.yml")
7
+ I18n.load_path += Dir.glob("#{locales_path}/*.yml")
8
8
 
9
9
  class Distance < M9t::Distance
10
-
11
10
  attr_accessor :units
12
11
 
13
12
  # nil is taken to mean 'data unavailable'
14
- def initialize( meters = nil )
13
+ def initialize(meters = nil)
15
14
  @units = :meters
16
15
  if meters
17
16
  super
@@ -21,19 +20,19 @@ module Metar
21
20
  end
22
21
 
23
22
  # Handles nil case differently to M9t::Distance
24
- def to_s( options = {} )
25
- options = { :units => @units,
26
- :precision => 0,
27
- :abbreviated => true }.merge( options )
23
+ def to_s(options = {})
24
+ options = {
25
+ :units => @units,
26
+ :precision => 0,
27
+ :abbreviated => true
28
+ }.merge(options)
28
29
  return I18n.t('metar.distance.unknown') if @value.nil?
29
- super( options )
30
+ super(options)
30
31
  end
31
-
32
32
  end
33
33
 
34
34
  # Adds a parse method to the M9t base class
35
35
  class Speed < M9t::Speed
36
-
37
36
  METAR_UNITS = {
38
37
  '' => :kilometers_per_hour,
39
38
  'KMH' => :kilometers_per_hour,
@@ -41,43 +40,39 @@ module Metar
41
40
  'KT' => :knots,
42
41
  }
43
42
 
44
- def Speed.parse(s)
43
+ def self.parse(s)
45
44
  case
46
45
  when s =~ /^(\d+)(|KT|MPS|KMH)$/
47
46
  # Call the appropriate factory method for the supplied units
48
- send( METAR_UNITS[$2], $1.to_i )
47
+ send(METAR_UNITS[$2], $1.to_i)
49
48
  else
50
49
  nil
51
50
  end
52
51
  end
53
-
54
52
  end
55
53
 
56
54
  # Adds a parse method to the M9t base class
57
55
  class Temperature < M9t::Temperature
58
-
59
- def Temperature.parse(s)
56
+ def self.parse(s)
60
57
  if s =~ /^(M?)(\d+)$/
61
58
  sign = $1
62
59
  value = $2.to_i
63
60
  value *= -1 if sign == 'M'
64
- new( value )
61
+ new(value)
65
62
  else
66
63
  nil
67
64
  end
68
65
  end
69
66
 
70
- def to_s( options = {} )
71
- options = { :abbreviated => true, :precision => 0 }.merge( options )
72
- super( options )
67
+ def to_s(options = {})
68
+ options = {:abbreviated => true, :precision => 0}.merge(options)
69
+ super(options)
73
70
  end
74
-
75
71
  end
76
72
 
77
73
  # Adds a parse method to the M9t base class
78
74
  class Pressure < M9t::Pressure
79
-
80
- def Pressure.parse(pressure)
75
+ def self.parse(pressure)
81
76
  case
82
77
  when pressure =~ /^Q(\d{4})$/
83
78
  hectopascals($1.to_f)
@@ -87,44 +82,34 @@ module Metar
87
82
  nil
88
83
  end
89
84
  end
90
-
91
85
  end
92
86
 
93
87
  class Direction < M9t::Direction
94
- def initialize( direction )
95
- direction = M9t::Direction::normalize( direction.to_f )
96
- super( direction )
88
+ def initialize(direction)
89
+ direction = M9t::Direction::normalize(direction.to_f)
90
+ super(direction)
97
91
  end
98
92
  end
99
93
 
100
94
  class Wind
101
-
102
- def Wind.parse(s)
95
+ def self.parse(s)
103
96
  case
104
97
  when s =~ /^(\d{3})(\d{2}(|MPS|KMH|KT))$/
105
98
  return nil if $1.to_i > 360
106
- new( Direction.new( $1 ),
107
- Speed.parse( $2 ) )
99
+ new(Direction.new($1), Speed.parse($2))
108
100
  when s =~ /^(\d{3})(\d{2})G(\d{2,3}(|MPS|KMH|KT))$/
109
101
  return nil if $1.to_i > 360
110
- new( Direction.new( $1 ),
111
- Speed.parse( $2 + $4 ),
112
- Speed.parse( $3 ) )
102
+ new(Direction.new($1), Speed.parse($2 + $4), Speed.parse($3))
113
103
  when s =~ /^VRB(\d{2})G(\d{2,3})(|MPS|KMH|KT)$/
114
104
  speed = $1 + $3
115
105
  gusts = $2 + $3
116
- new( :variable_direction,
117
- Speed.parse(speed),
118
- Speed.parse(gusts))
106
+ new(:variable_direction, Speed.parse(speed), Speed.parse(gusts))
119
107
  when s =~ /^VRB(\d{2}(|MPS|KMH|KT))$/
120
- new( :variable_direction,
121
- Speed.parse($1))
108
+ new(:variable_direction, Speed.parse($1))
122
109
  when s =~ /^\/{3}(\d{2}(|MPS|KMH|KT))$/
123
- new( :unknown_direction,
124
- Speed.parse($1))
110
+ new(:unknown_direction, Speed.parse($1))
125
111
  when s =~ %r(^/////(|MPS|KMH|KT)$)
126
- new( :unknown_direction,
127
- :unknown_speed)
112
+ new(:unknown_direction, :unknown_speed)
128
113
  else
129
114
  nil
130
115
  end
@@ -132,21 +117,25 @@ module Metar
132
117
 
133
118
  attr_reader :direction, :speed, :gusts
134
119
 
135
- def initialize( direction, speed, gusts = nil )
120
+ def initialize(direction, speed, gusts = nil)
136
121
  @direction, @speed, @gusts = direction, speed, gusts
137
122
  end
138
123
 
139
- def to_s( options = {} )
140
- options = { :direction_units => :compass,
141
- :speed_units => :kilometers_per_hour }.merge( options )
124
+ def to_s(options = {})
125
+ options = {
126
+ :direction_units => :compass,
127
+ :speed_units => :kilometers_per_hour
128
+ }.merge(options)
142
129
  speed =
143
130
  case @speed
144
131
  when :unknown_speed
145
132
  I18n.t('metar.wind.unknown_speed')
146
133
  else
147
- @speed.to_s( :abbreviated => true,
148
- :precision => 0,
149
- :units => options[ :speed_units ] )
134
+ @speed.to_s(
135
+ :abbreviated => true,
136
+ :precision => 0,
137
+ :units => options[:speed_units]
138
+ )
150
139
  end
151
140
  direction =
152
141
  case @direction
@@ -155,23 +144,23 @@ module Metar
155
144
  when :unknown_direction
156
145
  I18n.t('metar.wind.unknown_direction')
157
146
  else
158
- @direction.to_s( :units => options[ :direction_units ] )
147
+ @direction.to_s(:units => options[:direction_units])
159
148
  end
160
- s = "#{ speed } #{ direction }"
161
- if ! @gusts.nil?
162
- g = @gusts.to_s( :abbreviated => true,
163
- :precision => 0,
164
- :units => options[ :speed_units ] )
165
- s += " #{ I18n.t('metar.wind.gusts') } #{ g }"
149
+ s = "#{speed} #{direction}"
150
+ if not @gusts.nil?
151
+ g = @gusts.to_s(
152
+ :abbreviated => true,
153
+ :precision => 0,
154
+ :units => options[:speed_units]
155
+ )
156
+ s += " #{I18n.t('metar.wind.gusts')} #{g}"
166
157
  end
167
158
  s
168
159
  end
169
-
170
160
  end
171
161
 
172
162
  class VariableWind
173
-
174
- def VariableWind.parse(variable_wind)
163
+ def self.parse(variable_wind)
175
164
  if variable_wind =~ /^(\d+)V(\d+)$/
176
165
  new(Direction.new($1), Direction.new($2))
177
166
  else
@@ -186,38 +175,36 @@ module Metar
186
175
  end
187
176
 
188
177
  def to_s
189
- "#{ @direction1.to_s( :units => :compass ) } - #{ @direction2.to_s( :units => :compass ) }"
178
+ "#{@direction1.to_s(:units => :compass)} - #{@direction2.to_s(:units => :compass)}"
190
179
  end
191
-
192
180
  end
193
181
 
194
182
  class Visibility
195
-
196
- def Visibility.parse(s)
183
+ def self.parse(s)
197
184
  case
198
185
  when s == '9999'
199
- new( Distance.new( 10000 ), nil, :more_than )
186
+ new(Distance.new(10000), nil, :more_than)
200
187
  when s =~ /(\d{4})NDV/ # WMO
201
- new( Distance.new( $1.to_f ) ) # Assuming meters
188
+ new(Distance.new($1.to_f)) # Assuming meters
202
189
  when (s =~ /^((1|2)\s|)([1357])\/([248]|16)SM$/) # US
203
190
  miles = $1.to_f + $3.to_f / $4.to_f
204
- distance = Distance.miles( miles )
191
+ distance = Distance.miles(miles)
205
192
  distance.units = :miles
206
- new( distance )
193
+ new(distance)
207
194
  when s =~ /^(\d+)SM$/ # US
208
- distance = Distance.miles( $1.to_f )
195
+ distance = Distance.miles($1.to_f)
209
196
  distance.units = :miles
210
- new( distance )
197
+ new(distance)
211
198
  when s == 'M1/4SM' # US
212
- distance = Distance.miles( 0.25 )
199
+ distance = Distance.miles(0.25)
213
200
  distance.units = :miles
214
- new( distance, nil, :less_than )
201
+ new(distance, nil, :less_than)
215
202
  when s =~ /^(\d+)KM$/
216
- new( Distance.kilometers( $1 ) )
203
+ new(Distance.kilometers($1))
217
204
  when s =~ /^(\d+)$/ # We assume meters
218
- new( Distance.new( $1 ) )
205
+ new(Distance.new($1))
219
206
  when s =~ /^(\d+)(N|NE|E|SE|S|SW|W|NW)$/
220
- new( Distance.meters( $1 ), M9t::Direction.compass( $2 ) )
207
+ new(Distance.meters($1), M9t::Direction.compass($2))
221
208
  else
222
209
  nil
223
210
  end
@@ -229,36 +216,42 @@ module Metar
229
216
  @distance, @direction, @comparator = distance, direction, comparator
230
217
  end
231
218
 
232
- def to_s( options = {} )
233
- distance_options = { :abbreviated => true,
234
- :precision => 0,
235
- :units => :kilometers }.merge( options )
236
- direction_options = { :units => :compass }
219
+ def to_s(options = {})
220
+ distance_options = {
221
+ :abbreviated => true,
222
+ :precision => 0,
223
+ :units => :kilometers
224
+ }.merge(options)
225
+ direction_options = {:units => :compass}
237
226
  case
238
- when ( @direction.nil? and @comparator.nil? )
239
- @distance.to_s( distance_options )
227
+ when (@direction.nil? and @comparator.nil?)
228
+ @distance.to_s(distance_options)
240
229
  when @comparator.nil?
241
- "%s %s" % [ @distance.to_s( distance_options ),
242
- @direction.to_s( direction_options ) ]
230
+ [
231
+ @distance.to_s(distance_options),
232
+ @direction.to_s(direction_options)
233
+ ].join(' ')
243
234
  when @direction.nil?
244
- "%s %s" % [ I18n.t( 'comparison.' + @comparator.to_s ),
245
- @distance.to_s( distance_options ) ]
235
+ [
236
+ I18n.t('comparison.' + @comparator.to_s),
237
+ @distance.to_s(distance_options)
238
+ ].join(' ')
246
239
  else
247
- "%s %s %s" % [ I18n.t( 'comparison.' + @comparator.to_s ),
248
- @distance.to_s( distance_options ),
249
- @direction.to_s( direction_options ) ]
240
+ [
241
+ I18n.t('comparison.' + @comparator.to_s),
242
+ @distance.to_s(distance_options),
243
+ @direction.to_s(direction_options)
244
+ ].join(' ')
250
245
  end
251
246
  end
252
-
253
247
  end
254
248
 
255
249
  class RunwayVisibleRange
250
+ TENDENCY = {'' => nil, 'N' => :no_change, 'U' => :improving, 'D' => :worsening}
251
+ COMPARATOR = {'' => nil, 'P' => :more_than, 'M' => :less_than}
252
+ UNITS = {'' => :meters, 'FT' => :feet}
256
253
 
257
- TENDENCY = { '' => nil, 'N' => :no_change, 'U' => :improving, 'D' => :worsening }
258
- COMPARATOR = { '' => nil, 'P' => :more_than, 'M' => :less_than }
259
- UNITS = { '' => :meters, 'FT' => :feet }
260
-
261
- def RunwayVisibleRange.parse(runway_visible_range)
254
+ def self.parse(runway_visible_range)
262
255
  case
263
256
  when runway_visible_range =~ /^R(\d+[RLC]?)\/(P|M|)(\d{4})(N|U|D|)(FT|)$/
264
257
  designator = $1
@@ -266,7 +259,7 @@ module Metar
266
259
  count = $3.to_f
267
260
  tendency = TENDENCY[$4]
268
261
  units = UNITS[$5]
269
- distance = Distance.send( units, count )
262
+ distance = Distance.send(units, count)
270
263
  visibility = Visibility.new(distance, nil, comparator)
271
264
  new(designator, visibility, nil, tendency)
272
265
  when runway_visible_range =~ /^R(\d+[RLC]?)\/(P|M|)(\d{4})V(P|M|)(\d{4})(N|U|D)?(FT|)$/
@@ -277,50 +270,50 @@ module Metar
277
270
  count2 = $5.to_f
278
271
  tendency = TENDENCY[$6]
279
272
  units = UNITS[$7]
280
- distance1 = Distance.send( units, count1 )
281
- distance2 = Distance.send( units, count2 )
282
- visibility1 = Visibility.new( distance1, nil, comparator1 )
283
- visibility2 = Visibility.new( distance2, nil, comparator2 )
284
- new( designator, visibility1, visibility2, tendency, units )
273
+ distance1 = Distance.send(units, count1)
274
+ distance2 = Distance.send(units, count2)
275
+ visibility1 = Visibility.new(distance1, nil, comparator1)
276
+ visibility2 = Visibility.new(distance2, nil, comparator2)
277
+ new(designator, visibility1, visibility2, tendency, units)
285
278
  else
286
279
  nil
287
280
  end
288
281
  end
289
282
 
290
283
  attr_reader :designator, :visibility1, :visibility2, :tendency
291
- def initialize( designator, visibility1, visibility2 = nil, tendency = nil, units = :meters )
284
+ def initialize(designator, visibility1, visibility2 = nil, tendency = nil, units = :meters)
292
285
  @designator, @visibility1, @visibility2, @tendency, @units = designator, visibility1, visibility2, tendency, units
293
286
  end
294
287
 
295
288
  def to_s
296
- distance_options = { :abbreviated => true,
297
- :precision => 0,
298
- :units => @units }
289
+ distance_options = {
290
+ :abbreviated => true,
291
+ :precision => 0,
292
+ :units => @units
293
+ }
299
294
  s =
300
295
  if @visibility2.nil?
301
- I18n.t( 'metar.runway_visible_range.runway') +
302
- ' ' + @designator +
303
- ': ' + @visibility1.to_s( distance_options )
296
+ I18n.t('metar.runway_visible_range.runway') +
297
+ ' ' + @designator +
298
+ ': ' + @visibility1.to_s(distance_options)
304
299
  else
305
- I18n.t( 'metar.runway_visible_range.runway') +
306
- ' ' + @designator +
307
- ': ' + I18n.t('metar.runway_visible_range.from') +
308
- ' ' + @visibility1.to_s( distance_options ) +
309
- ' ' + I18n.t('metar.runway_visible_range.to') +
310
- ' ' + @visibility2.to_s( distance_options )
300
+ I18n.t('metar.runway_visible_range.runway') +
301
+ ' ' + @designator +
302
+ ': ' + I18n.t('metar.runway_visible_range.from') +
303
+ ' ' + @visibility1.to_s(distance_options) +
304
+ ' ' + I18n.t('metar.runway_visible_range.to') +
305
+ ' ' + @visibility2.to_s(distance_options)
311
306
  end
312
307
 
313
308
  if ! tendency.nil?
314
- s += ' ' + I18n.t( "tendency.#{ tendency }" )
309
+ s += ' ' + I18n.t("tendency.#{tendency}")
315
310
  end
316
311
 
317
312
  s
318
313
  end
319
-
320
314
  end
321
315
 
322
316
  class WeatherPhenomenon
323
-
324
317
  Modifiers = {
325
318
  '+' => 'heavy',
326
319
  '-' => 'light',
@@ -368,21 +361,21 @@ module Metar
368
361
  }
369
362
 
370
363
  # Accepts all standard (and some non-standard) present weather codes
371
- def WeatherPhenomenon.parse(s)
364
+ def self.parse(s)
372
365
  phenomena = Phenomena.keys.join('|')
373
366
  descriptors = Descriptors.keys.join('|')
374
367
  modifiers = Modifiers.keys.join('|')
375
368
  modifiers.gsub!(/([\+\-])/) { "\\#$1" }
376
- rxp = Regexp.new("^(#{ modifiers })?(#{ descriptors })?((?:#{ phenomena }){1,2})$")
369
+ rxp = Regexp.new("^(#{modifiers})?(#{descriptors})?((?:#{phenomena}){1,2})$")
377
370
  m = rxp.match(s)
378
371
  return nil if m.nil?
379
372
 
380
373
  modifier_code = m[1]
381
374
  descriptor_code = m[2]
382
375
  phenomena_codes = m[3].scan(/../)
383
- phenomena_phrase = phenomena_codes.map{ |c| Phenomena[c] }.join(' and ')
376
+ phenomena_phrase = phenomena_codes.map { |c| Phenomena[c] }.join(' and ')
384
377
 
385
- Metar::WeatherPhenomenon.new(phenomena_phrase, Modifiers[modifier_code], Descriptors[descriptor_code])
378
+ new(phenomena_phrase, Modifiers[modifier_code], Descriptors[descriptor_code])
386
379
  end
387
380
 
388
381
  attr_reader :phenomenon, :modifier, :descriptor
@@ -393,11 +386,9 @@ module Metar
393
386
  def to_s
394
387
  I18n.t("metar.present_weather.%s" % [@modifier, @descriptor, @phenomenon].compact.join(' '))
395
388
  end
396
-
397
389
  end
398
390
 
399
391
  class SkyCondition
400
-
401
392
  QUANTITY = {'BKN' => 'broken', 'FEW' => 'few', 'OVC' => 'overcast', 'SCT' => 'scattered'}
402
393
  CONDITION = {
403
394
  'CB' => 'cumulonimbus',
@@ -412,22 +403,22 @@ module Metar
412
403
  'SKC',
413
404
  ]
414
405
 
415
- def SkyCondition.parse(sky_condition)
406
+ def self.parse(sky_condition)
416
407
  case
417
- when CLEAR_SKIES.include?( sky_condition )
408
+ when CLEAR_SKIES.include?(sky_condition)
418
409
  new
419
410
  when sky_condition =~ /^(BKN|FEW|OVC|SCT)(\d+|\/{3})(CB|TCU|\/{3}|)?$/
420
- quantity = QUANTITY[ $1 ]
411
+ quantity = QUANTITY[$1]
421
412
  height =
422
413
  if $2 == '///'
423
414
  nil
424
415
  else
425
- Distance.new( $2.to_i * 30.48 )
416
+ Distance.new($2.to_i * 30.48)
426
417
  end
427
- type = CONDITION[ $3 ]
418
+ type = CONDITION[$3]
428
419
  new(quantity, height, type)
429
420
  when sky_condition =~ /^(CB|TCU)$/
430
- type = CONDITION[ $1 ]
421
+ type = CONDITION[$1]
431
422
  new(nil, nil, type)
432
423
  else
433
424
  nil
@@ -452,29 +443,25 @@ module Metar
452
443
  I18n.t('metar.sky_conditions.clear skies')
453
444
  else
454
445
  type = @type ? ' ' + @type : ''
455
- I18n.t("metar.sky_conditions.#{ @quantity }#{ type }")
446
+ I18n.t("metar.sky_conditions.#{@quantity}#{type}")
456
447
  end
457
448
  end
458
-
459
449
  end
460
450
 
461
451
  class VerticalVisibility
462
-
463
- def VerticalVisibility.parse( vertical_visibility )
452
+ def self.parse(vertical_visibility)
464
453
  case
465
454
  when vertical_visibility =~ /^VV(\d{3})$/
466
- Distance.new( $1.to_f * 30.48 )
455
+ Distance.new($1.to_f * 30.48)
467
456
  when vertical_visibility == '///'
468
457
  Distance.new
469
458
  else
470
459
  nil
471
460
  end
472
461
  end
473
-
474
462
  end
475
463
 
476
464
  class Remark
477
-
478
465
  PRESSURE_CHANGE_CHARACTER = [
479
466
  :increasing_then_decreasing, # 0
480
467
  :increasing_then_steady, # 1
@@ -488,7 +475,7 @@ module Metar
488
475
  ]
489
476
 
490
477
  INDICATOR_TYPE = {
491
- 'TS' => :thunderstorm_information,
478
+ 'TS' => :thunderstorm_information,
492
479
  'PWI' => :precipitation_identifier,
493
480
  'P' => :precipitation_amount,
494
481
  }
@@ -556,89 +543,20 @@ module Metar
556
543
  def self.inches_to_meters(digits)
557
544
  digits.to_f * 0.000254
558
545
  end
559
-
560
- end
561
-
562
- class TemperatureExtreme
563
-
564
- attr_accessor :value
565
- attr_accessor :extreme
566
-
567
- def initialize(extreme, value)
568
- @extreme, @value = extreme, value
569
- end
570
-
571
546
  end
572
547
 
573
- class PressureTendency
574
-
575
- attr_accessor :value
576
- attr_accessor :character
548
+ TemperatureExtreme = Struct.new(:extreme, :value)
549
+ PressureTendency = Struct.new(:character, :value)
550
+ Precipitation = Struct.new(:period, :amount)
551
+ AutomatedStationType = Struct.new(:type)
552
+ HourlyTemperaturAndDewPoint = Struct.new(:temperature, :dew_point)
553
+ SeaLevelPressure = Struct.new(:pressure)
554
+ SensorStatusIndicator = Struct.new(:type, :state)
555
+ ColorCode = Struct.new(:code)
577
556
 
578
- def initialize(character, value)
579
- @character, @value = character, value
580
- end
581
-
582
- end
583
-
584
- class Precipitation
585
-
586
- attr_accessor :period
587
- attr_accessor :amount
588
-
589
- def initialize(period, amount)
590
- @period, @amount = period, amount
591
- end
592
-
593
- end
594
-
595
- class AutomatedStationType
596
-
597
- attr_accessor :type
598
-
599
- def initialize(type)
600
- @type = type
601
- end
602
-
603
- end
604
-
605
- class HourlyTemperaturAndDewPoint
606
-
607
- attr_accessor :temperature
608
- attr_accessor :dew_point
609
-
610
- def initialize(temperature, dew_point)
611
- @temperature, @dew_point = temperature, dew_point
612
- end
613
-
614
- end
615
-
616
- class SeaLevelPressure
617
-
618
- attr_accessor :pressure
619
-
620
- def initialize(pressure)
621
- @pressure = pressure
622
- end
623
-
624
- end
625
-
626
- class SensorStatusIndicator
627
-
628
- attr_accessor :type
629
- attr_accessor :state
630
-
631
- def initialize(type, state)
632
- @type, @state = type, state
633
- end
634
-
635
- end
636
-
637
- class MaintenanceNeeded
638
- end
557
+ class MaintenanceNeeded; end
639
558
 
640
559
  class Lightning
641
-
642
560
  TYPE = {'' => :default}
643
561
 
644
562
  def self.parse_chunks(chunks)
@@ -695,18 +613,15 @@ module Metar
695
613
  end
696
614
 
697
615
  class VisibilityRemark < Visibility
698
-
699
616
  def self.parse(chunk)
700
617
  chunk =~ /^(\d{4})([NESW]?)$/
701
618
  distance = Distance.new($1)
702
619
 
703
620
  new(distance, $2, :more_than)
704
621
  end
705
-
706
622
  end
707
623
 
708
624
  class DensityAltitude
709
-
710
625
  def self.parse(chunk)
711
626
  chunk =~ /^(\d+)(FT)$/
712
627
  height = Distance.feet($1)
@@ -719,18 +634,6 @@ module Metar
719
634
  def initialize(height)
720
635
  @height = height
721
636
  end
722
-
723
- end
724
-
725
- class ColorCode
726
-
727
- attr_accessor :code
728
-
729
- def initialize(code)
730
- @code = code
731
- end
732
-
733
637
  end
734
-
735
638
  end
736
639
 
data/lib/metar/parser.rb CHANGED
@@ -301,7 +301,11 @@ module Metar
301
301
  break if @chunks.size == 0
302
302
  r = Metar::Remark.parse(@chunks[0])
303
303
  if r
304
- @remarks += [*r]
304
+ if r.is_a?(Array)
305
+ @remarks += r
306
+ else
307
+ @remarks << r
308
+ end
305
309
  @chunks.shift
306
310
  next
307
311
  end
data/lib/metar/report.rb CHANGED
@@ -40,7 +40,7 @@ module Metar
40
40
  end
41
41
 
42
42
  def time
43
- "%u:%u" % [@parser.time.hour, @parser.time.min]
43
+ "%u:%02u" % [@parser.time.hour, @parser.time.min]
44
44
  end
45
45
 
46
46
  def observer
data/lib/metar/version.rb CHANGED
@@ -2,7 +2,7 @@ module Metar
2
2
  module VERSION #:nodoc:
3
3
  MAJOR = 1
4
4
  MINOR = 1
5
- TINY = 4
5
+ TINY = 5
6
6
 
7
7
  STRING = [MAJOR, MINOR, TINY].join('.')
8
8
  end
@@ -1,32 +1,28 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ require 'spec_helper'
3
3
 
4
4
  describe Metar::Parser do
5
-
6
- after :each do
5
+ after do
7
6
  Metar::Parser.compliance = :loose
8
7
  end
9
8
 
10
9
  context '.for_cccc' do
11
-
12
10
  it 'returns a loaded parser' do
13
- station = stub( 'station' )
14
- raw = stub( 'raw', :metar => "XXXX 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000",
15
- :time => '2010/02/06 16:10' )
16
- Metar::Station.stub!( :new => station )
17
- Metar::Raw::Noaa.stub!( :new => raw )
11
+ station = stub('station')
12
+ raw = stub('raw', :metar => "XXXX 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000",
13
+ :time => '2010/02/06 16:10')
14
+ Metar::Station.stub!(:new => station)
15
+ Metar::Raw::Noaa.stub!(:new => raw)
18
16
 
19
- parser = Metar::Parser.for_cccc( 'XXXX' )
17
+ parser = Metar::Parser.for_cccc('XXXX')
20
18
 
21
- parser. should be_a( Metar::Parser )
22
- parser.station_code. should == 'XXXX'
19
+ expect(parser).to be_a(Metar::Parser)
20
+ expect(parser.station_code).to eq('XXXX')
23
21
  end
24
-
25
22
  end
26
23
 
27
24
  context 'attributes' do
28
-
29
- before :each do
25
+ before do
30
26
  @call_time = Time.parse('2011-05-06 16:35')
31
27
  Time.stub!(:now).and_return(@call_time)
32
28
  end
@@ -34,315 +30,262 @@ describe Metar::Parser do
34
30
  it '.location missing' do
35
31
  expect do
36
32
  setup_parser("FUBAR 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
37
- end. to raise_error( Metar::ParseError, /Expecting location/ )
33
+ end.to raise_error(Metar::ParseError, /Expecting location/)
38
34
  end
39
35
 
40
36
  context 'datetime' do
41
-
42
37
  it 'is parsed' do
43
38
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
44
39
 
45
- parser.time. should == Time.gm(2011, 05, 06, 16, 10)
40
+ expect(parser.time).to eq(Time.gm(2011, 05, 06, 16, 10))
46
41
  end
47
42
 
48
43
  it 'throws an error is missing' do
49
44
  expect do
50
45
  setup_parser("PAIL 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
51
- end. to raise_error( Metar::ParseError, /Expecting datetime/ )
46
+ end.to raise_error(Metar::ParseError, /Expecting datetime/)
52
47
  end
53
48
 
54
49
  context 'in strict mode' do
55
-
56
- before :each do
50
+ before do
57
51
  Metar::Parser.compliance = :strict
58
52
  end
59
53
 
60
54
  it 'less than 6 numerals fails' do
61
55
  expect do
62
56
  parser = setup_parser('MMCE 21645Z 12010KT 8SM SKC 29/26 A2992 RMK')
63
- end. to raise_error(Metar::ParseError, /Expecting datetime/)
57
+ end.to raise_error(Metar::ParseError, /Expecting datetime/)
64
58
  end
65
-
66
59
  end
67
60
 
68
61
  context 'in loose mode' do
69
-
70
62
  it '5 numerals parses' do
71
63
  parser = setup_parser('MMCE 21645Z 12010KT 8SM SKC 29/26 A2992 RMK')
72
64
 
73
- parser.time. should == Time.gm(2011, 05, 02, 16, 45)
65
+ expect(parser.time).to eq(Time.gm(2011, 05, 02, 16, 45))
74
66
  end
75
67
 
76
68
  it "with 4 numerals parses, takes today's day" do
77
69
  parser = setup_parser('HKML 1600Z 19010KT 9999 FEW022 25/22 Q1015')
78
70
 
79
- parser.time. should == Time.gm(2011, 05, 06, 16, 00)
71
+ expect(parser.time).to eq(Time.gm(2011, 05, 06, 16, 00))
80
72
  end
81
-
82
73
  end
83
-
84
74
  end
85
75
 
86
76
  context '.observer' do
87
-
88
77
  it 'real' do
89
78
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
90
79
 
91
- parser.observer. should == :real
80
+ expect(parser.observer).to eq(:real)
92
81
  end
93
82
 
94
83
  it 'auto' do
95
84
  parser = setup_parser("CYXS 151034Z AUTO 09003KT 1/8SM FZFG VV001 M03/M03 A3019 RMK SLP263 ICG")
96
85
 
97
- parser.observer. should == :auto
86
+ expect(parser.observer).to eq(:auto)
98
87
  end
99
88
 
100
89
  it 'corrected' do
101
90
  parser = setup_parser("PAIL 061610Z COR 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
102
91
 
103
- parser.observer. should == :corrected
92
+ expect(parser.observer).to eq(:corrected)
104
93
  end
105
94
 
106
95
  it 'corrected (Canadian)' do
107
96
  parser = setup_parser('CYZU 310100Z CCA 26004KT 15SM FEW009 BKN040TCU BKN100 OVC210 15/12 A2996 RETS RMK SF1TCU4AC2CI1 SLP149')
108
97
 
109
- parser.observer. should == :corrected
98
+ expect(parser.observer).to eq(:corrected)
110
99
  end
111
-
112
100
  end
113
101
 
114
102
  it 'wind' do
115
103
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
116
104
 
117
- parser.wind.direction.value.should be_within( 0.0001 ).of( 240 )
118
- parser.wind.speed.to_knots. should be_within( 0.0001 ).of( 6 )
105
+ expect(parser.wind.direction.value).to be_within(0.0001).of(240)
106
+ expect(parser.wind.speed.to_knots).to be_within(0.0001).of(6)
119
107
  end
120
108
 
121
109
  it 'variable_wind' do
122
110
  parser = setup_parser("LIRQ 061520Z 01007KT 350V050 9999 SCT035 BKN080 08/02 Q1005")
123
111
 
124
- parser.variable_wind.direction1.value.
125
- should be_within( 0.0001 ).of( 350 )
126
- parser.variable_wind.direction2.value.
127
- should be_within( 0.0001 ).of( 50 )
112
+ expect(parser.variable_wind.direction1.value).to be_within(0.0001).of(350)
113
+ expect(parser.variable_wind.direction2.value).to be_within(0.0001).of(50)
128
114
  end
129
115
 
130
116
  context '.visibility' do
131
117
  it 'CAVOK' do
132
118
  parser = setup_parser("PAIL 061610Z 24006KT CAVOK M17/M20 A2910 RMK AO2 P0000")
133
119
 
134
- parser.visibility.distance.value.
135
- should be_within( 0.01 ).of( 10000.00 )
136
- parser.visibility.comparator.
137
- should == :more_than
138
- parser.present_weather.size.
139
- should == 1
140
- parser.present_weather[ 0 ].phenomenon.
141
- should == 'No significant weather'
142
- parser.sky_conditions.size.
143
- should == 1
144
- parser.sky_conditions[ 0 ].type.
145
- should == nil
120
+ expect(parser.visibility.distance.value).to be_within(0.01).of(10000.00)
121
+ expect(parser.visibility.comparator).to eq(:more_than)
122
+ expect(parser.present_weather.size).to eq(1)
123
+ expect(parser.present_weather[0].phenomenon).to eq('No significant weather')
124
+ expect(parser.sky_conditions.size).to eq(1)
125
+ expect(parser.sky_conditions[0].type).to eq(nil)
146
126
  end
147
127
 
148
128
  it 'visibility_miles_and_fractions' do
149
129
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
150
130
 
151
- parser.visibility.distance.to_miles.
152
- should be_within( 0.01 ).of( 1.75 )
131
+ expect(parser.visibility.distance.to_miles).to be_within(0.01).of(1.75)
153
132
  end
154
133
 
155
134
  it 'in meters' do
156
135
  parser = setup_parser('VABB 282210Z 22005KT 4000 HZ SCT018 FEW025TCU BKN100 28/25 Q1003 NOSIG')
157
136
 
158
- parser.visibility.distance.value.
159
- should be_within(0.01).of(4000)
137
+ expect(parser.visibility.distance.value).to be_within(0.01).of(4000)
160
138
  end
161
139
 
162
140
  it '//// with automatic observer' do
163
141
  parser = setup_parser("CYXS 151034Z AUTO 09003KT //// FZFG VV001 M03/M03 A3019 RMK SLP263 ICG")
164
142
 
165
- parser.visibility. should be_nil
143
+ expect(parser.visibility).to be_nil
166
144
  end
167
145
  end
168
146
 
169
147
  it 'runway_visible_range' do
170
148
  parser = setup_parser("ESSB 151020Z 26003KT 2000 R12/1000N R30/1500N VV002 M07/M07 Q1013 1271//55")
171
- parser.runway_visible_range.length.
172
- should == 2
173
- parser.runway_visible_range[0].designator.
174
- should == '12'
175
- parser.runway_visible_range[0].visibility1.distance.value.
176
- should == 1000
177
- parser.runway_visible_range[0].tendency.
178
- should == :no_change
149
+ expect(parser.runway_visible_range.size).to eq(2)
150
+ expect(parser.runway_visible_range[0].designator).to eq('12')
151
+ expect(parser.runway_visible_range[0].visibility1.distance.value).to eq(1000)
152
+ expect(parser.runway_visible_range[0].tendency).to eq(:no_change)
179
153
  end
180
154
 
181
155
  it 'runway_visible_range_defaults_to_empty_array' do
182
156
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
183
157
 
184
- parser.runway_visible_range.length.
185
- should == 0
158
+ expect(parser.runway_visible_range.size).to eq(0)
186
159
  end
187
160
 
188
161
  it 'runway_visible_range_variable' do
189
162
  parser = setup_parser("KPDX 151108Z 11006KT 1/4SM R10R/1600VP6000FT FG OVC002 05/05 A3022 RMK AO2")
190
163
 
191
- parser.runway_visible_range[0].visibility1.distance.to_feet.
192
- should == 1600.0
193
- parser.runway_visible_range[0].visibility2.distance.to_feet.
194
- should == 6000.0
164
+ expect(parser.runway_visible_range[0].visibility1.distance.to_feet).to eq(1600.0)
165
+ expect(parser.runway_visible_range[0].visibility2.distance.to_feet).to eq(6000.0)
195
166
  end
196
167
 
197
168
  context '.present_weather' do
198
-
199
169
  it 'normal' do
200
170
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
201
171
 
202
- parser.present_weather.size.
203
- should == 1
204
- parser.present_weather[0].modifier.
205
- should == 'light'
206
- parser.present_weather[0].phenomenon.
207
- should == 'snow'
172
+ expect(parser.present_weather.size).to eq(1)
173
+ expect(parser.present_weather[0].modifier).to eq('light')
174
+ expect(parser.present_weather[0].phenomenon).to eq('snow')
208
175
  end
209
176
 
210
177
  it 'auto + //' do
211
178
  parser = setup_parser("PAIL 061610Z AUTO 24006KT 1 3/4SM // BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
212
179
 
213
- parser.present_weather.size.
214
- should == 1
215
- parser.present_weather[0].phenomenon.
216
- should == 'not observed'
180
+ expect(parser.present_weather.size).to eq(1)
181
+ expect(parser.present_weather[0].phenomenon).to eq('not observed')
217
182
  end
218
-
219
183
  end
220
184
 
221
185
  it 'present_weather_defaults_to_empty_array' do
222
186
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
223
- parser.present_weather.length.
224
- should == 0
187
+ expect(parser.present_weather.size).to eq(0)
225
188
  end
226
189
 
227
190
  context '.sky_conditions' do
228
-
229
191
  it 'normal' do
230
192
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
231
193
 
232
- parser.sky_conditions.size.
233
- should == 2
234
- parser.sky_conditions[0].quantity.
235
- should == 'broken'
236
- parser.sky_conditions[0].height.value.
237
- should == 487.68
238
- parser.sky_conditions[1].quantity.
239
- should == 'overcast'
240
- parser.sky_conditions[1].height.value.
241
- should == 914.40
194
+ expect(parser.sky_conditions.size).to eq(2)
195
+ expect(parser.sky_conditions[0].quantity).to eq('broken')
196
+ expect(parser.sky_conditions[0].height.value).to eq(487.68)
197
+ expect(parser.sky_conditions[1].quantity).to eq('overcast')
198
+ expect(parser.sky_conditions[1].height.value).to eq(914.40)
242
199
  end
243
200
 
244
201
  it 'auto + ///' do
245
202
  parser = setup_parser("PAIL 061610Z AUTO 24006KT 1 3/4SM /// M17/M20 A2910 RMK AO2 P0000")
246
203
 
247
- parser.sky_conditions.size.
248
- should == 0
204
+ expect(parser.sky_conditions.size).to eq(0)
249
205
  end
250
-
251
206
  end
252
207
 
253
208
  it 'sky_conditions_defaults_to_empty_array' do
254
209
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN M17/M20 A2910 RMK AO2 P0000")
255
- parser.sky_conditions.length.
256
- should == 0
210
+ expect(parser.sky_conditions.size).to eq(0)
257
211
  end
258
212
 
259
213
  it 'vertical_visibility' do
260
214
  parser = setup_parser("CYXS 151034Z AUTO 09003KT 1/8SM FZFG VV001 M03/M03 A3019 RMK SLP263 ICG")
261
- parser.vertical_visibility.value.
262
- should == 30.48
215
+ expect(parser.vertical_visibility.value).to eq(30.48)
263
216
  end
264
217
 
265
218
  it 'temperature' do
266
219
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
267
- parser.temperature.value. should == -17
220
+ expect(parser.temperature.value).to eq(-17)
268
221
  end
269
222
 
270
223
  it 'dew_point' do
271
224
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
272
- parser.dew_point.value. should == -20
225
+ expect(parser.dew_point.value).to eq(-20)
273
226
  end
274
227
 
275
228
  it 'sea_level_pressure' do
276
229
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
277
- parser.sea_level_pressure.to_inches_of_mercury.
278
- should == 29.10
230
+ expect(parser.sea_level_pressure.to_inches_of_mercury).to eq(29.10)
279
231
  end
280
232
 
281
233
  it 'recent weather' do
282
234
  parser = setup_parser("CYQH 310110Z 00000KT 20SM SCT035CB BKN050 RETS RMK CB4SC1")
283
235
 
284
- parser.recent_weather. should be_a Array
285
- parser.recent_weather.size. should == 1
286
- parser.recent_weather[0].phenomenon.
287
- should == 'thunderstorm'
236
+ expect(parser.recent_weather).to be_a Array
237
+ expect(parser.recent_weather.size).to eq(1)
238
+ expect(parser.recent_weather[0].phenomenon).to eq('thunderstorm')
288
239
  end
289
240
 
290
241
  context 'remarks' do
291
-
292
242
  it 'are collected' do
293
243
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
294
244
 
295
- parser.remarks. should be_a Array
296
- parser.remarks.size. should == 2
245
+ expect(parser.remarks).to be_a Array
246
+ expect(parser.remarks.size).to eq(2)
297
247
  end
298
248
 
299
249
  it 'remarks defaults to empty array' do
300
250
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910")
301
251
 
302
- parser.remarks. should be_a Array
303
- parser.remarks.length. should == 0
252
+ expect(parser.remarks).to be_a Array
253
+ expect(parser.remarks.size).to eq(0)
304
254
  end
305
255
 
306
256
  it 'parses known remarks' do
307
257
  parser = setup_parser('CYZT 052200Z 31010KT 20SM SKC 17/12 A3005 RMK SLP174 20046')
308
258
 
309
- parser.remarks[0]. should be_a(Metar::SeaLevelPressure)
310
- parser.remarks[1]. should be_temperature_extreme(:minimum, 4.6)
259
+ expect(parser.remarks[0]).to be_a(Metar::SeaLevelPressure)
260
+ expect(parser.remarks[1]).to be_temperature_extreme(:minimum, 4.6)
311
261
  end
312
262
 
313
263
  context 'in strict mode' do
314
-
315
- before :each do
264
+ before do
316
265
  Metar::Parser.compliance = :strict
317
266
  end
318
267
 
319
268
  it 'unparsed data causes an error' do
320
269
  expect do
321
270
  setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 FOO RMK AO2 P0000")
322
- end. to raise_error(Metar::ParseError, /Unparsable text found/)
271
+ end.to raise_error(Metar::ParseError, /Unparsable text found/)
323
272
  end
324
-
325
273
  end
326
274
 
327
275
  context 'in loose mode' do
328
-
329
276
  it 'unparsed data is collected' do
330
277
  parser = setup_parser("PAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 FOO RMK AO2 P0000")
331
278
 
332
- parser.unparsed. should == ['FOO']
333
- parser.remarks.size. should == 2
279
+ expect(parser.unparsed).to eq(['FOO'])
280
+ expect(parser.remarks.size).to eq(2)
334
281
  end
335
-
336
282
  end
337
-
338
283
  end
339
284
 
340
285
  def setup_parser(metar)
341
286
  raw = Metar::Raw::Data.new(metar)
342
287
  Metar::Parser.new(raw)
343
288
  end
344
-
345
289
  end
346
-
347
290
  end
348
291
 
@@ -49,6 +49,12 @@ describe Metar::Report do
49
49
 
50
50
  context '#time' do
51
51
  specify { subject.time. should == @metar_time }
52
+
53
+ it 'zero-pads single figure minutes' do
54
+ @parser.stub(:time => Time.parse('10:02'))
55
+
56
+ expect(subject.time).to eq('10:02')
57
+ end
52
58
  end
53
59
 
54
60
  context '#observer' do
@@ -1,9 +1,9 @@
1
1
  # encoding: utf-8
2
- load File.expand_path( '../spec_helper.rb', File.dirname(__FILE__) )
2
+ load File.expand_path('../spec_helper.rb', File.dirname(__FILE__))
3
3
 
4
- RSpec::Matchers.define :be_wind do | direction, speed, gusts |
5
- match do | wind |
6
- if wind.nil? && [ direction, speed, gusts ].all?( &:nil? )
4
+ RSpec::Matchers.define :be_wind do |direction, speed, gusts|
5
+ match do |wind|
6
+ if wind.nil? && [direction, speed, gusts].all?(&:nil?)
7
7
  true
8
8
  elsif wind.nil?
9
9
  false
@@ -13,15 +13,15 @@ RSpec::Matchers.define :be_wind do | direction, speed, gusts |
13
13
  false
14
14
  elsif wind.gusts.nil? != gusts.nil?
15
15
  false
16
- elsif direction.is_a?( Symbol ) && wind.direction != direction
16
+ elsif direction.is_a?(Symbol) && wind.direction != direction
17
17
  false
18
- elsif direction.is_a?( M9t::Direction ) && (wind.direction.value - direction).abs > 0.01
18
+ elsif direction.is_a?(M9t::Direction) && (wind.direction.value - direction).abs > 0.01
19
19
  false
20
- elsif speed.is_a?( Symbol ) && wind.speed != speed
20
+ elsif speed.is_a?(Symbol) && wind.speed != speed
21
21
  false
22
- elsif speed.is_a?( Metar::Speed ) && (wind.speed.value - speed).abs > 0.01
22
+ elsif speed.is_a?(Metar::Speed) && (wind.speed.value - speed).abs > 0.01
23
23
  false
24
- elsif ! wind.gusts.nil? && (wind.gusts.value - gusts).abs > 0.01
24
+ elsif ! wind.gusts.nil? && (wind.gusts.value - gusts).abs > 0.01
25
25
  false
26
26
  else
27
27
  true
@@ -30,52 +30,48 @@ RSpec::Matchers.define :be_wind do | direction, speed, gusts |
30
30
  end
31
31
 
32
32
  describe Metar::Wind do
33
-
34
33
  context '.parse' do
35
-
36
34
  [
37
35
  # Direction and speed
38
- [ 'treats 5 digits as degrees and kilometers per hour', '12345', [ 123.0, 12.50, nil ] ],
39
- [ 'understands 5 digits + KMH', '12345KMH', [ 123.0, 12.50, nil ] ],
40
- [ 'understands 5 digits + MPS', '12345MPS', [ 123.0, 45.00, nil ] ],
41
- [ 'understands 5 digits + KT', '12345KT', [ 123.0, 23.15, nil ] ],
42
- [ 'rounds 360 down to 0', '36045KT', [ 0.0, 23.15, nil ] ],
43
- [ 'returns nil for directions outside 0 to 360', '88845KT', [ nil, nil, nil ] ],
36
+ ['treats 5 digits as degrees and kilometers per hour', '12345', [123.0, 12.50, nil]],
37
+ ['understands 5 digits + KMH', '12345KMH', [123.0, 12.50, nil]],
38
+ ['understands 5 digits + MPS', '12345MPS', [123.0, 45.00, nil]],
39
+ ['understands 5 digits + KT', '12345KT', [123.0, 23.15, nil]],
40
+ ['rounds 360 down to 0', '36045KT', [ 0.0, 23.15, nil]],
41
+ ['returns nil for directions outside 0 to 360', '88845KT', [nil, nil, nil]],
44
42
  # +gusts
45
- [ 'understands 5 digits + G + 2 digits', '12345G67', [ 123.0, 12.50, 18.61 ] ],
46
- [ 'understands 5 digits + G + 2 digits + KMH', '12345G67KMH', [ 123.0, 12.50, 18.61 ] ],
47
- [ 'understands 5 digits + G + 2 digits + MPS', '12345G67MPS', [ 123.0, 45.00, 67.00 ] ],
48
- [ 'understands 5 digits + G + 2 digits + KT', '12345G67KT', [ 123.0, 23.15, 34.47 ] ],
43
+ ['understands 5 digits + G + 2 digits', '12345G67', [123.0, 12.50, 18.61]],
44
+ ['understands 5 digits + G + 2 digits + KMH', '12345G67KMH', [123.0, 12.50, 18.61]],
45
+ ['understands 5 digits + G + 2 digits + MPS', '12345G67MPS', [123.0, 45.00, 67.00]],
46
+ ['understands 5 digits + G + 2 digits + KT', '12345G67KT', [123.0, 23.15, 34.47]],
49
47
  # Variable direction
50
- [ 'understands VRB + 2 digits' 'VRB12', [ :variable_direction, 3.33, nil ] ],
51
- [ 'understands VRB + 2 digits + KMH', 'VRB12KMH', [ :variable_direction, 3.33, nil ] ],
52
- [ 'understands VRB + 2 digits + MPS', 'VRB12MPS', [ :variable_direction, 12.00, nil ] ],
53
- [ 'understands VRB + 2 digits + KT', 'VRB12KT', [ :variable_direction, 6.17, nil ] ],
48
+ ['understands VRB + 2 digits', 'VRB12', [:variable_direction, 3.33, nil]],
49
+ ['understands VRB + 2 digits + KMH', 'VRB12KMH', [:variable_direction, 3.33, nil]],
50
+ ['understands VRB + 2 digits + MPS', 'VRB12MPS', [:variable_direction, 12.00, nil]],
51
+ ['understands VRB + 2 digits + KT', 'VRB12KT', [:variable_direction, 6.17, nil]],
54
52
  # + gusts
55
- [ 'understands VRB + 2 digits + G + 2 digits', 'VRB45G67', [ :variable_direction, 12.50, 18.61 ] ],
56
- [ 'understands VRB + 2 digits + G + 2 digits + KMH', 'VRB45G67KMH', [ :variable_direction, 12.50, 18.61 ] ],
57
- [ 'understands VRB + 2 digits + G + 2 digits + MPS', 'VRB45G67MPS', [ :variable_direction, 45.00, 67.00 ] ],
58
- [ 'understands VRB + 2 digits + G + 2 digits + KT', 'VRB45G67KT', [ :variable_direction, 23.15, 34.47 ] ],
53
+ ['understands VRB + 2 digits + G + 2 digits', 'VRB45G67', [:variable_direction, 12.50, 18.61]],
54
+ ['understands VRB + 2 digits + G + 2 digits + KMH', 'VRB45G67KMH', [:variable_direction, 12.50, 18.61]],
55
+ ['understands VRB + 2 digits + G + 2 digits + MPS', 'VRB45G67MPS', [:variable_direction, 45.00, 67.00]],
56
+ ['understands VRB + 2 digits + G + 2 digits + KT', 'VRB45G67KT', [:variable_direction, 23.15, 34.47]],
59
57
  # Unknown direction
60
- [ 'understands /// + 2 digits', '///12', [ :unknown_direction, 3.33, nil ] ],
61
- [ 'understands /// + 2 digits + KMH', '///12KMH', [ :unknown_direction, 3.33, nil ] ],
62
- [ 'understands /// + 2 digits + MPS', '///12MPS', [ :unknown_direction, 12.00, nil ] ],
63
- [ 'understands /// + 2 digits + KT', '///12KT', [ :unknown_direction, 6.17, nil ] ],
58
+ ['understands /// + 2 digits', '///12', [:unknown_direction, 3.33, nil]],
59
+ ['understands /// + 2 digits + KMH', '///12KMH', [:unknown_direction, 3.33, nil]],
60
+ ['understands /// + 2 digits + MPS', '///12MPS', [:unknown_direction, 12.00, nil]],
61
+ ['understands /// + 2 digits + KT', '///12KT', [:unknown_direction, 6.17, nil]],
64
62
  # Unknown direction and speed
65
- [ 'understands /////', '/////', [ :unknown_direction, :unknown_speed, nil ] ],
63
+ ['understands /////', '/////', [:unknown_direction, :unknown_speed, nil]],
66
64
  # Bad data
67
- [ 'returns nil for badly formatted values', 'XYZ12KT', [ nil, nil, nil ] ],
68
- [ 'returns nil for nil', nil, [ nil, nil, nil ] ],
69
- ].each do | docstring, raw, expected |
65
+ ['returns nil for badly formatted values', 'XYZ12KT', [nil, nil, nil]],
66
+ ['returns nil for nil', nil, [nil, nil, nil]],
67
+ ].each do |docstring, raw, expected|
70
68
  example docstring do
71
- Metar::Wind.parse( raw ).should be_wind( *expected )
69
+ Metar::Wind.parse(raw).should be_wind(*expected)
72
70
  end
73
71
  end
74
-
75
72
  end
76
73
 
77
74
  context '#to_s' do
78
-
79
75
  before :each do
80
76
  @locale = I18n.locale
81
77
  I18n.locale = :it
@@ -86,28 +82,26 @@ describe Metar::Wind do
86
82
  end
87
83
 
88
84
  [
89
- [ 'should format speed and direction', :en, [ nil, nil, nil ], '443km/h ESE' ],
90
- [ 'should handle variable_direction', :en, [ :variable_direction, nil, nil ], '443km/h variable direction' ],
91
- [ 'should handle unknown_direction', :en, [ :unknown_direction, nil, nil ], '443km/h unknown direction' ],
92
- [ 'should handle unknown_speed', :en, [ nil, :unknown_speed, nil ], 'unknown speed ESE' ],
93
- [ 'should include gusts', :en, [ nil, nil, Metar::Speed.new( 123 ) ], '443km/h ESE gusts 443km/h' ],
94
- [ 'should format speed and direction', :it, [ nil, nil, nil ], '443km/h ESE' ],
95
- [ 'should handle variable_direction', :it, [ :variable_direction, nil, nil ], '443km/h direzione variabile' ],
96
- [ 'should handle unknown_direction', :it, [ :unknown_direction, nil, nil ], '443km/h direzione sconosciuta' ],
97
- [ 'should handle unknown_speed', :it, [ nil, :unknown_speed, nil ], 'velocità sconosciuta ESE' ],
98
- [ 'should include gusts', :it, [ nil, nil, Metar::Speed.new( 123 ) ], '443km/h ESE folate di 443km/h' ],
99
- ].each do | docstring, locale, ( direction, speed, gusts ), expected |
100
- direction ||= M9t::Direction.new( 123 )
101
- speed ||= Metar::Speed.new( 123 )
85
+ ['should format speed and direction', :en, [nil, nil, nil ], '443km/h ESE' ],
86
+ ['should handle variable_direction', :en, [:variable_direction, nil, nil ], '443km/h variable direction' ],
87
+ ['should handle unknown_direction', :en, [:unknown_direction, nil, nil ], '443km/h unknown direction' ],
88
+ ['should handle unknown_speed', :en, [nil, :unknown_speed, nil ], 'unknown speed ESE' ],
89
+ ['should include gusts', :en, [nil, nil, Metar::Speed.new(123)], '443km/h ESE gusts 443km/h' ],
90
+ ['should format speed and direction', :it, [nil, nil, nil ], '443km/h ESE' ],
91
+ ['should handle variable_direction', :it, [:variable_direction, nil, nil ], '443km/h direzione variabile' ],
92
+ ['should handle unknown_direction', :it, [:unknown_direction, nil, nil ], '443km/h direzione sconosciuta'],
93
+ ['should handle unknown_speed', :it, [nil, :unknown_speed, nil ], 'velocità sconosciuta ESE' ],
94
+ ['should include gusts', :it, [nil, nil, Metar::Speed.new(123)], '443km/h ESE folate di 443km/h'],
95
+ ].each do |docstring, locale, (direction, speed, gusts), expected|
96
+ direction ||= M9t::Direction.new(123)
97
+ speed ||= Metar::Speed.new(123)
102
98
 
103
99
  example docstring + " (#{locale})" do
104
100
  I18n.locale = locale
105
- Metar::Wind.new( direction, speed, gusts ).to_s.
101
+ Metar::Wind.new(direction, speed, gusts).to_s.
106
102
  should == expected
107
103
  end
108
104
  end
109
-
110
105
  end
111
-
112
106
  end
113
107
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metar-parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-24 00:00:00.000000000 Z
12
+ date: 2013-05-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -194,7 +194,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
194
194
  version: '0'
195
195
  segments:
196
196
  - 0
197
- hash: 256504047505018704
197
+ hash: 2864761200794302878
198
198
  required_rubygems_version: !ruby/object:Gem::Requirement
199
199
  none: false
200
200
  requirements:
@@ -203,7 +203,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
203
  version: '0'
204
204
  segments:
205
205
  - 0
206
- hash: 256504047505018704
206
+ hash: 2864761200794302878
207
207
  requirements: []
208
208
  rubyforge_project: nowarning
209
209
  rubygems_version: 1.8.23