metar-parser 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
data/lib/metar/data.rb CHANGED
@@ -41,9 +41,9 @@ module Metar
41
41
  case
42
42
  when s =~ /^(\d+)(KT|MPS|KMH)$/
43
43
  # Call the appropriate factory method for the supplied units
44
- send(METAR_UNITS[$2], $1.to_i, { :units => METAR_UNITS[$2], :precision => 0 })
44
+ send(METAR_UNITS[$2], $1.to_i, { :units => :kilometers_per_hour, :precision => 0, :abbreviated => true })
45
45
  when s =~ /^(\d+)$/
46
- kilometers_per_hour($1.to_i, { :units => :kilometers_per_hour, :precision => 0 })
46
+ kilometers_per_hour($1.to_i, { :units => :kilometers_per_hour, :precision => 0, :abbreviated => true })
47
47
  else
48
48
  nil
49
49
  end
@@ -88,9 +88,9 @@ module Metar
88
88
  def Wind.parse(s)
89
89
  case
90
90
  when s =~ /^(\d{3})(\d{2}(|MPS|KMH|KT))$/
91
- new(M9t::Direction.new($1, { :abbreviated => true }), Speed.parse($2))
91
+ new(M9t::Direction.new($1, { :units => :compass, :abbreviated => true }), Speed.parse($2))
92
92
  when s =~ /^(\d{3})(\d{2})G(\d{2,3}(|MPS|KMH|KT))$/
93
- new(M9t::Direction.new($1, { :abbreviated => true }), Speed.parse($2))
93
+ new(M9t::Direction.new($1, { :units => :compass, :abbreviated => true }), Speed.parse($2))
94
94
  when s =~ /^VRB(\d{2}(|MPS|KMH|KT))$/
95
95
  new(:variable_direction, Speed.parse($1))
96
96
  when s =~ /^\/{3}(\d{2}(|MPS|KMH|KT))$/
@@ -125,7 +125,7 @@ module Metar
125
125
  else
126
126
  @speed.to_s
127
127
  end
128
- "#{ direction }, #{ speed }"
128
+ "#{ speed } #{ direction }"
129
129
  end
130
130
 
131
131
  end
@@ -325,7 +325,7 @@ module Metar
325
325
  def to_s
326
326
  modifier = @modifier ? @modifier + ' ' : ''
327
327
  descriptor = @descriptor ? @descriptor + ' ' : ''
328
- I18n.t("metar.weather.%s%s%s" % [modifier, descriptor, @phenomenon])
328
+ I18n.t("metar.present_weather.%s%s%s" % [modifier, descriptor, @phenomenon])
329
329
  end
330
330
 
331
331
  end
@@ -333,6 +333,7 @@ module Metar
333
333
  class SkyCondition
334
334
 
335
335
  QUANTITY = {'BKN' => 'broken', 'FEW' => 'few', 'OVC' => 'overcast', 'SCT' => 'scattered'}
336
+
336
337
  def SkyCondition.parse(sky_condition)
337
338
  case
338
339
  when (sky_condition == 'NSC' or sky_condition == 'NCD') # WMO
@@ -355,7 +356,7 @@ module Metar
355
356
  when '///'
356
357
  nil
357
358
  else
358
- raise MetarParserError.new("Unexpected sky condition type: #$3")
359
+ raise ParseError.new("Unexpected sky condition type: #$3")
359
360
  end
360
361
  new(quantity, height, type)
361
362
  else
@@ -369,11 +370,17 @@ module Metar
369
370
  end
370
371
 
371
372
  def to_s
373
+ conditions = to_summary
374
+ conditions += ' ' + I18n.t('metar.altitude.at') + ' ' + height.to_s if not @height.nil?
375
+ conditions
376
+ end
377
+
378
+ def to_summary
372
379
  if @quantity == nil and @height == nil and @type == nil
373
380
  I18n.t('metar.sky_conditions.clear skies')
374
381
  else
375
382
  type = @type ? ' ' + @type : ''
376
- I18n.t("metar.sky_conditions.#{ @quantity }#{ type }") + ' ' + I18n.t('metar.altitude.at') + ' ' + height.to_s
383
+ I18n.t("metar.sky_conditions.#{ @quantity }#{ type }")
377
384
  end
378
385
  end
379
386
 
data/lib/metar/parser.rb CHANGED
@@ -4,9 +4,6 @@ require File.join(File.dirname(__FILE__), 'data')
4
4
 
5
5
  module Metar
6
6
 
7
- class ParseError < StandardError
8
- end
9
-
10
7
  class Parser
11
8
  include AASM
12
9
 
@@ -95,7 +92,7 @@ module Metar
95
92
  parser
96
93
  end
97
94
 
98
- attr_reader :station_code, :time, :observer, :wind, :variable_wind, :visibility, :runway_visible_range,
95
+ attr_reader :station_code, :observer, :time, :wind, :variable_wind, :visibility, :runway_visible_range,
99
96
  :present_weather, :sky_conditions, :vertical_visibility, :temperature, :dew_point, :sea_level_pressure, :remarks
100
97
 
101
98
  def initialize(raw)
@@ -104,26 +101,6 @@ module Metar
104
101
  analyze
105
102
  end
106
103
 
107
- def attributes
108
- h = {
109
- :station_code => @location.clone,
110
- :time => @time.to_s,
111
- :observer => Report.symbol_to_s(@observer)
112
- }
113
- h[:wind] = @wind if @wind
114
- h[:variable_wind] = @variable_wind.clone if @variable_wind
115
- h[:visibility] = @visibility if @visibility
116
- h[:runway_visible_range] = @runway_visible_range if @runway_visible_range
117
- h[:present_weather] = @present_weather if @present_weather
118
- h[:sky_conditions] = @sky_conditions if @sky_conditions
119
- h[:vertical_visibility] = @vertical_visibility if @vertical_visibility
120
- h[:temperature] = @temperature
121
- h[:dew_point] = @dew_point
122
- h[:sea_level_pressure] = @sea_level_pressure
123
- h[:remarks] = @remarks.clone if @remarks
124
- h
125
- end
126
-
127
104
  def date
128
105
  Date.new(@time.year, @time.month, @time.day)
129
106
  end
@@ -133,26 +110,26 @@ module Metar
133
110
  def analyze
134
111
  @chunks = @metar.split(' ')
135
112
 
136
- @location = nil
113
+ @station_code = nil
137
114
  @observer = :real
138
115
  @wind = nil
139
116
  @variable_wind = nil
140
117
  @visibility = nil
141
- @runway_visible_range = nil
142
- @present_weather = nil
143
- @sky_conditions = nil
118
+ @runway_visible_range = []
119
+ @present_weather = []
120
+ @sky_conditions = []
144
121
  @vertical_visibility = nil
145
122
  @temperature = nil
146
123
  @dew_point = nil
147
124
  @sea_level_pressure = nil
148
- @remarks = nil
125
+ @remarks = []
149
126
 
150
127
  aasm_enter_initial_state
151
128
  end
152
129
 
153
130
  def seek_location
154
131
  if @chunks[0] =~ /^[A-Z][A-Z0-9]{3}$/
155
- @location = @chunks.shift
132
+ @station_code = @chunks.shift
156
133
  else
157
134
  raise ParseError.new("Expecting location, found '#{ @chunks[0] }'")
158
135
  end
@@ -204,18 +181,15 @@ module Metar
204
181
  if @chunks[0] == 'CAVOK'
205
182
  @chunks.shift
206
183
  @visibility = Visibility.new(M9t::Distance.kilometers(10), nil, :more_than)
207
- @present_weather ||= []
208
184
  @present_weather << Metar::WeatherPhenomenon.new('No significant weather')
209
- @sky_conditions ||= []
210
- @sky_conditions << 'No significant cloud' # TODO: What does NSC stand for?
185
+ @sky_conditions << SkyCondition.new # = 'clear skies'
211
186
  cavok!
212
187
  return
213
188
  end
214
189
 
215
190
  if @observer == :auto # WMO 15.4
216
191
  if @chunks[0] == '////'
217
- @chunks.shift
218
- @visibility = Visibility.new('Not observed')
192
+ @chunks.shift # Simply dispose of it
219
193
  visibility!
220
194
  return
221
195
  end
@@ -242,7 +216,6 @@ module Metar
242
216
  runway_visible_range = RunwayVisibleRange.parse(@chunks[0])
243
217
  if runway_visible_range
244
218
  @chunks.shift
245
- @runway_visible_range ||= []
246
219
  @runway_visible_range << runway_visible_range
247
220
  collect_runway_visible_range
248
221
  end
@@ -257,7 +230,6 @@ module Metar
257
230
  wtp = WeatherPhenomenon.parse(@chunks[0])
258
231
  if wtp
259
232
  @chunks.shift
260
- @present_weather ||= []
261
233
  @present_weather << wtp
262
234
  collect_present_weather
263
235
  end
@@ -266,7 +238,7 @@ module Metar
266
238
  def seek_present_weather
267
239
  if @observer == :auto
268
240
  if @chunks[0] == '//' # WMO 15.4
269
- @present_weather ||= []
241
+ @chunks.shift # Simply dispose of it
270
242
  @present_weather << Metar::WeatherPhenomenon.new('not observed')
271
243
  present_weather!
272
244
  return
@@ -281,7 +253,6 @@ module Metar
281
253
  sky_condition = SkyCondition.parse(@chunks[0])
282
254
  if sky_condition
283
255
  @chunks.shift
284
- @sky_conditions ||= []
285
256
  @sky_conditions << sky_condition
286
257
  collect_sky_conditions
287
258
  end
@@ -290,9 +261,7 @@ module Metar
290
261
  def seek_sky_conditions
291
262
  if @observer == :auto # WMO 15.4
292
263
  if @chunks[0] == '///' or @chunks[0] == '//////'
293
- @chunks.shift
294
- @sky_conditions ||= []
295
- @sky_conditions << 'Not observed'
264
+ @chunks.shift # Simply dispose of it
296
265
  sky_conditions!
297
266
  return
298
267
  end
@@ -336,7 +305,6 @@ module Metar
336
305
  if @chunks[0] == 'RMK'
337
306
  @chunks.shift
338
307
  end
339
- @remarks ||= []
340
308
  @remarks += @chunks.clone
341
309
  @chunks = []
342
310
  remarks!
data/lib/metar/report.rb CHANGED
@@ -1,10 +1,63 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module Metar
4
+
4
5
  class Report
5
6
 
7
+ KNOWN_ATTRIBUTES =
8
+ [
9
+ :station_code, :station_name, :station_country,
10
+ :date, :time, :observer,
11
+ :wind, :variable_wind,
12
+ :visibility, :runway_visible_range,
13
+ :present_weather,
14
+ :sky_summary, :sky_conditions,
15
+ :temperature, :dew_point, :remarks
16
+ ]
17
+
18
+ DEFAULT_ATTRIBUTES =
19
+ [
20
+ :station_name, :station_country,
21
+ :time,
22
+ :wind,
23
+ :visibility,
24
+ :present_weather,
25
+ :sky_summary,
26
+ :temperature
27
+ ]
28
+
29
+ instance_eval do
30
+
31
+ def reset_options!
32
+ @attributes = DEFAULT_ATTRIBUTES.clone
33
+ end
34
+
35
+ def attributes
36
+ @attributes
37
+ end
38
+
39
+ def attributes=(attributes)
40
+ @attributes = attributes.clone
41
+ end
42
+
43
+ reset_options!
44
+ end
45
+
6
46
  def initialize(parser)
7
47
  @parser = parser
48
+ @station = Station.find_by_cccc(@parser.station_code)
49
+ end
50
+
51
+ def station_name
52
+ @station.name
53
+ end
54
+
55
+ def station_country
56
+ @station.country
57
+ end
58
+
59
+ def station_code
60
+ @parser.station_code
8
61
  end
9
62
 
10
63
  def date
@@ -15,6 +68,10 @@ module Metar
15
68
  "%u:%u" % [@parser.time.hour, @parser.time.min]
16
69
  end
17
70
 
71
+ def observer
72
+ I18n.t('metar.observer.' + @parser.observer.to_s)
73
+ end
74
+
18
75
  def wind
19
76
  @parser.wind.to_s
20
77
  end
@@ -35,6 +92,11 @@ module Metar
35
92
  @parser.present_weather.to_s
36
93
  end
37
94
 
95
+ def sky_summary
96
+ return I18n.t('metar.sky_conditions.clear skies') if @parser.sky_conditions.length == 0
97
+ @parser.sky_conditions[-1].to_summary
98
+ end
99
+
38
100
  def sky_conditions
39
101
  @parser.sky_conditions.collect { |sky| sky.to_s }.join(', ')
40
102
  end
@@ -55,41 +117,24 @@ module Metar
55
117
  @parser.sea_level_pressure.to_s
56
118
  end
57
119
 
58
- end
59
- end
60
-
61
- __END__
62
-
63
-
64
- def attributes_to_s
65
- attrib = attributes
66
- texts = {}
67
- texts[:wind] = attrib[:wind] if attrib[:wind]
68
- texts[:variable_wind] = attrib[:variable_wind] if attrib[:variable_wind]
69
- texts[:visibility] = "%u meters" % attrib[:visibility].value if attrib[:visibility]
70
- texts[:runway_visible_range] = attrib[:runway_visible_range].join(', ') if attrib[:runway_visible_range]
71
- texts[:present_weather] = attrib[:present_weather].join(', ') if attrib[:present_weather]
72
- texts[:sky_conditions] = attrib[:sky_conditions].join(', ') if attrib[:sky_conditions]
73
- texts[:temperature] = "%u celcius" % attrib[:temperature] if attrib[:temperature]
74
- texts[:dew_point] = "%u celcius" % attrib[:dew_point] if attrib[:dew_point]
75
- texts[:remarks] = attrib[:remarks].join(', ') if attrib[:remarks]
76
-
77
- texts
120
+ def remarks
121
+ @parser.remarks.join(', ')
122
+ end
123
+
124
+ def attributes
125
+ Metar::Report.attributes.reduce([]) do |memo, key|
126
+ value = self.send(key).to_s
127
+ memo << {:attribute => key, :value => value} if not value.empty?
128
+ memo
129
+ end
78
130
  end
79
131
 
80
132
  def to_s
81
- # If attributes supplied an ordered hash, the hoop-jumping below
82
- # wouldn't be necessary
83
- attr = attributes_to_s
84
- [:station_code, :time, :observer, :wind, :variable_wind, :visibility, :runway_visible_range,
85
- :present_weather, :sky_conditions, :temperature, :dew_point, :remarks].collect do |key|
86
- attr[key] ? self.symbol_to_s(key) + ": " + attr[key] : nil
87
- end.compact.join("\n")
133
+ attributes.collect do |attribute|
134
+ I18n.t('metar.' + attribute[:attribute].to_s + '.title') + ': ' + attribute[:value]
135
+ end.join("\n")
88
136
  end
89
137
 
90
- private
138
+ end
91
139
 
92
- # :symbol_etc => 'Symbol etc'
93
- def self.symbol_to_s(sym)
94
- sym.to_s.gsub(/^([a-z])/) {$1.upcase}.gsub(/_([a-z])/) {" #$1"}
95
- end
140
+ end
data/lib/metar/station.rb CHANGED
@@ -23,7 +23,7 @@ module Metar
23
23
  end
24
24
 
25
25
  # Load local copy of the station list
26
- # and download it first if missing
26
+ # and download it first if missing
27
27
  def load_local
28
28
  download_local if not File.exist?(Metar::Station.local_nsd_path)
29
29
  @nsd_cccc = File.open(Metar::Station.local_nsd_path) do |fil|
@@ -39,15 +39,15 @@ module Metar
39
39
  end
40
40
  end
41
41
 
42
- def find_by_cccc(cccc)
43
- all.find { |station| station.cccc == cccc }
44
- end
45
-
46
42
  # Does the given CCCC code exist?
47
43
  def exist?(cccc)
48
44
  not find_data_by_cccc(cccc).nil?
49
45
  end
50
46
 
47
+ def find_by_cccc(cccc)
48
+ all.find { |station| station.cccc == cccc }
49
+ end
50
+
51
51
  def to_longitude(s)
52
52
  s =~ /^(\d+)-(\d+)([EW])/ or return nil
53
53
  ($3 == 'E' ? 1.0 : -1.0) * ($1.to_f + $2.to_f / 60.0)
data/lib/metar.rb CHANGED
@@ -8,7 +8,7 @@ module Metar
8
8
  module VERSION #:nodoc:
9
9
  MAJOR = 0
10
10
  MINOR = 1
11
- TINY = 3
11
+ TINY = 4
12
12
 
13
13
  STRING = [MAJOR, MINOR, TINY].join('.')
14
14
  end
@@ -18,7 +18,7 @@ module Metar
18
18
  end
19
19
 
20
20
  # Raised when an unrecognized value is found
21
- class MetarParserError < MetarError
21
+ class ParseError < MetarError
22
22
  end
23
23
 
24
24
  end
data/locales/en.yml CHANGED
@@ -11,15 +11,37 @@ en:
11
11
  bar:
12
12
  full: bar
13
13
  metar:
14
+ station_code:
15
+ title: station code
16
+ station_name:
17
+ title: name
18
+ station_country:
19
+ title: country
20
+ time:
21
+ title: time
22
+ observer:
23
+ title: observer
24
+ real: real
25
+ auto: automatic
26
+ corrected: corrected
14
27
  altitude:
15
28
  at: at
16
29
  distance:
30
+ title: distance
17
31
  unknown: unknown
18
32
  wind:
33
+ title: wind
19
34
  variable_direction: variable direction
20
35
  unknown_direction: unknown direction
21
36
  unknown_speed: unknown speed
37
+ variable_wind:
38
+ title: wind variation
39
+ visibility:
40
+ title: visibility
41
+ sky_summary:
42
+ title: sky
22
43
  sky_conditions:
44
+ title: sky conditions
23
45
  clear skies: clear skies
24
46
  broken: broken cloud
25
47
  broken cumulonimbus: broken cumulonimbus
@@ -32,10 +54,13 @@ en:
32
54
  scattered towering cumulus: scattered towering cumulus clouds
33
55
  overcast: overcast
34
56
  runway_visible_range:
57
+ title: runway visible range
35
58
  runway: runway
36
59
  from: from
37
60
  to: to
38
- weather:
61
+ present_weather:
62
+ title: weather
63
+ not observed: not observed
39
64
  mist: mist
40
65
  dust: dust
41
66
  blowing dust: blowing dust
@@ -119,3 +144,9 @@ en:
119
144
  light thunderstorm and unknown phenomenon: light thunderstorm and unknown phenomenon
120
145
  heavy unknown phenomenon: heavy unknown phenomenon
121
146
  light unknown phenomenon: light unknown phenomenon
147
+ temperature:
148
+ title: temperature
149
+ dew_point:
150
+ title: punto di rugiada
151
+ remarks:
152
+ title: annotazioni
data/locales/it.yml CHANGED
@@ -11,15 +11,37 @@ it:
11
11
  bar:
12
12
  full: bar
13
13
  metar:
14
+ station_code:
15
+ title: codice stazione
16
+ station_name:
17
+ title: nome
18
+ station_country:
19
+ title: nazione
20
+ time:
21
+ title: ora
22
+ observer:
23
+ title: osservatore
24
+ real: reale
25
+ auto: automazzato
26
+ corrected: corretto
14
27
  altitude:
15
28
  at: a
16
29
  distance:
30
+ title: distanza
17
31
  unknown: sconosciuto
18
32
  wind:
33
+ title: vento
19
34
  variable_direction: direzione variabile
20
35
  unknown_direction: direzione sconosciuta
21
36
  unknown_speed: velocità sconosciuta
37
+ variable_wind:
38
+ title: variazione del vento
39
+ visibility:
40
+ title: visibilità
41
+ sky_summary:
42
+ title: cielo
22
43
  sky_conditions:
44
+ title: condizioni del cielo
23
45
  clear skies: cielo sereno
24
46
  broken: nuvolosità parziale
25
47
  broken cumulonimbus: copertura parziale di cumulonembi
@@ -32,10 +54,13 @@ it:
32
54
  scattered towering cumulus: cumulonembi sparsi
33
55
  overcast: chiuso
34
56
  runway_visible_range:
57
+ title: visibilità sulle piste
35
58
  runway: pista
36
59
  from: da
37
60
  to: a
38
- weather:
61
+ present_weather:
62
+ title: tempo
63
+ not observed: non osservato
39
64
  mist: foschia
40
65
  dust: polvere
41
66
  blowing dust: polviscolo
@@ -119,3 +144,9 @@ it:
119
144
  light thunderstorm and unknown phenomenon: temporale con fenomeno sconosciuto leggero
120
145
  heavy unknown phenomenon: fenomeno sconosciuto intenso
121
146
  light unknown phenomenon: fenomeno sconosciuto leggero
147
+ temperature:
148
+ title: temperatura
149
+ dew_point:
150
+ title: punto di rugiada
151
+ remarks:
152
+ title: annotazioni
@@ -11,4 +11,23 @@ Metar::Raw.instance_eval do
11
11
  end
12
12
  end
13
13
 
14
+ # Don't load station data from files
15
+ module Metar
16
+ class Station
17
+
18
+ class << self
19
+
20
+ def all_structures
21
+ [
22
+ { :cccc => 'LIRQ', :country => 'Italy', :latitude => '43-48N', :longitude => '011-12E', :name => 'Firenze / Peretola', :state => '' },
23
+ { :cccc => 'DAAS', :country => 'Algeria', :latitude => '36-11N', :longitude => '005-25E', :name => 'Setif', :state => '' },
24
+ { :cccc => 'ESSB', :country => 'Sweden', :latitude => '59-21N', :longitude => '017-57E',:name => 'Stockholm / Bromma', :state => '' },
25
+ { :cccc => 'KPDX', :country => 'United States', :latitude => '45-35N', :longitude => '122-36W', :name => 'PORTLAND INTERNATIONAL AIRPORT', :state => '' },
26
+ { :cccc => 'CYXS', :country => 'Canada', :latitude => '53-53N', :longitude => '122-41W', :name => 'Prince George, B. C.', :state => '' },
27
+ ]
28
+ end
29
+ end
30
+ end
31
+ end
32
+
14
33
  require 'test/unit'
@@ -43,26 +43,31 @@ class TestMetarData < Test::Unit::TestCase
43
43
  assert_not_nil(Metar::Speed.options)
44
44
  end
45
45
 
46
- def test_speed_parse_default_unit
46
+ def test_speed_parse_without_units
47
47
  speed = Metar::Speed.parse('12')
48
48
  assert_equal(12, speed.to_kilometers_per_hour)
49
- assert_equal(:kilometers_per_hour, speed.options[:units])
50
49
  end
51
50
 
52
51
  def test_speed_parse_kilometers_per_hour
53
52
  speed = Metar::Speed.parse('12KMH')
54
53
  assert_equal(12, speed.to_kilometers_per_hour)
55
- assert_equal(:kilometers_per_hour, speed.options[:units])
56
54
  end
57
55
 
58
56
  def test_speed_parse_knots
59
57
  speed = Metar::Speed.parse('12KT')
60
- assert_equal(:knots, speed.options[:units])
58
+ assert_equal(12.0, speed.to_knots)
59
+ assert_equal(:kilometers_per_hour, speed.options[:units])
61
60
  end
62
61
 
63
- def test_speed_parse_meters_per_second
62
+ def test_speed_parse_kilometers_per_hour_is_default
63
+ speed = Metar::Speed.parse('12')
64
+ assert_equal(:kilometers_per_hour, speed.options[:units])
64
65
  speed = Metar::Speed.parse('12MPS')
65
- assert_equal(:meters_per_second, speed.options[:units])
66
+ assert_equal(:kilometers_per_hour, speed.options[:units])
67
+ speed = Metar::Speed.parse('12KMH')
68
+ assert_equal(:kilometers_per_hour, speed.options[:units])
69
+ speed = Metar::Speed.parse('12KT')
70
+ assert_equal(:kilometers_per_hour, speed.options[:units])
66
71
  end
67
72
 
68
73
  # Temperature
@@ -104,55 +109,65 @@ class TestMetarData < Test::Unit::TestCase
104
109
  end
105
110
 
106
111
  # Wind
107
- def test_wind_parse_default_units
112
+ def test_wind_parse_without_units
108
113
  wind = Metar::Wind.parse('18012')
109
114
  assert_equal(180, wind.direction.value)
110
115
  assert_equal(12.0, wind.speed.to_kilometers_per_hour)
111
- assert_equal(:kilometers_per_hour, wind.speed.options[:units])
112
116
  end
113
117
 
114
118
  def test_wind_parse_mps
115
119
  wind = Metar::Wind.parse('18012MPS')
116
120
  assert_equal(180, wind.direction.value)
117
121
  assert_equal(12.0, wind.speed.value)
118
- assert_equal(:meters_per_second, wind.speed.options[:units])
119
122
  end
120
123
 
121
124
  def test_wind_parse_kmh
122
125
  wind = Metar::Wind.parse('27012KMH')
123
126
  assert_equal(270, wind.direction.value)
124
127
  assert_equal(12.0, wind.speed.to_kilometers_per_hour)
125
- assert_equal(:kilometers_per_hour, wind.speed.options[:units])
126
128
  end
127
129
 
128
130
  def test_wind_parse_knots
129
131
  wind = Metar::Wind.parse('24006KT')
130
132
  assert_equal(240, wind.direction.value)
131
133
  assert_equal(6, wind.speed.to_knots)
132
- assert_equal(:knots, wind.speed.options[:units])
134
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
133
135
  end
134
136
 
135
137
  def test_wind_parse_variable_direction
136
138
  wind = Metar::Wind.parse('VRB20KT')
137
139
  assert_equal(:variable_direction, wind.direction)
138
140
  assert_equal(20, wind.speed.to_knots)
139
- assert_equal(:knots, wind.speed.options[:units])
140
- assert_equal('variable direction, 20 knots', wind.to_s)
141
+ assert_equal('37km/h variable direction', wind.to_s)
141
142
  end
142
143
 
143
144
  def test_wind_parse_unknown_direction
144
145
  wind = Metar::Wind.parse('///20KT')
145
146
  assert_equal(:unknown_direction, wind.direction)
146
147
  assert_equal(20, wind.speed.to_knots)
147
- assert_equal(:knots, wind.speed.options[:units])
148
- assert_equal('unknown direction, 20 knots', wind.to_s)
148
+ assert_equal('37km/h unknown direction', wind.to_s)
149
149
  end
150
150
 
151
151
  def test_wind_parse_unknown_direction_and_speed
152
152
  wind = Metar::Wind.parse('/////')
153
153
  assert_equal(:unknown_direction, wind.direction)
154
154
  assert_equal(:unknown, wind.speed)
155
- assert_equal('unknown direction, unknown speed', wind.to_s)
155
+ assert_equal('unknown speed unknown direction', wind.to_s)
156
+ end
157
+
158
+ def test_wind_parse_default_output_units_kilometers_per_hour
159
+ wind = Metar::Wind.parse('18012')
160
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
161
+ wind = Metar::Wind.parse('18012MPS')
162
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
163
+ wind = Metar::Wind.parse('27012KMH')
164
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
165
+ wind = Metar::Wind.parse('24006KT')
166
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
167
+ wind = Metar::Wind.parse('VRB20KT')
168
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
169
+ wind = Metar::Wind.parse('///20KT')
170
+ assert_equal(:kilometers_per_hour, wind.speed.options[:units])
156
171
  end
157
172
 
158
173
  # VariableWind
@@ -15,11 +15,22 @@ class TestMetarParser < Test::Unit::TestCase
15
15
  end
16
16
  end
17
17
 
18
+ def test_time_obligatory
19
+ assert_raise(Metar::ParseError) {
20
+ setup_parser('PAIL', "2010/02/06 16:10\nPAIL 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
21
+ }
22
+ end
23
+
18
24
  def test_date
19
25
  parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
20
26
  assert_equal(Date.new(2010, 2, 6), parser.date)
21
27
  end
22
28
 
29
+ def test_observer_real
30
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
31
+ assert_equal(:real, parser.observer)
32
+ end
33
+
23
34
  def test_wind
24
35
  parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
25
36
  assert_in_delta(240, parser.wind.direction.value, 0.0001)
@@ -46,6 +57,11 @@ class TestMetarParser < Test::Unit::TestCase
46
57
  assert_equal(:no_change, parser.runway_visible_range[0].tendency)
47
58
  end
48
59
 
60
+ def test_runway_visible_range_defaults_to_empty_array
61
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
62
+ assert_equal(0, parser.runway_visible_range.length)
63
+ end
64
+
49
65
  def test_runway_visible_range_variable
50
66
  parser = setup_parser('KPDX', "2010/02/15 11:08\nKPDX 151108Z 11006KT 1/4SM R10R/1600VP6000FT FG OVC002 05/05 A3022 RMK AO2")
51
67
  assert_equal(1600.0, parser.runway_visible_range[0].visibility1.distance.to_feet)
@@ -61,6 +77,11 @@ class TestMetarParser < Test::Unit::TestCase
61
77
  assert_equal('snow', parser.present_weather[0].phenomenon)
62
78
  end
63
79
 
80
+ def test_present_weather_defaults_to_empty_array
81
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
82
+ assert_equal(0, parser.present_weather.length)
83
+ end
84
+
64
85
  def test_sky_conditions
65
86
  parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
66
87
  assert_equal(2, parser.sky_conditions.length)
@@ -70,11 +91,22 @@ class TestMetarParser < Test::Unit::TestCase
70
91
  assert_equal(900, parser.sky_conditions[1].height.value)
71
92
  end
72
93
 
94
+ def test_sky_conditions_defaults_to_empty_array
95
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN M17/M20 A2910 RMK AO2 P0000")
96
+ assert_equal(0, parser.sky_conditions.length)
97
+ end
98
+
73
99
  def test_vertical_visibility
74
100
  parser = setup_parser('CYXS', "2010/02/15 10:34\nCYXS 151034Z AUTO 09003KT 1/8SM FZFG VV001 M03/M03 A3019 RMK SLP263 ICG")
75
101
  assert_equal(30, parser.vertical_visibility.value)
76
102
  end
77
103
 
104
+ def test_temperature_obligatory
105
+ assert_raise(Metar::ParseError) {
106
+ setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 A2910 RMK AO2 P0000")
107
+ }
108
+ end
109
+
78
110
  def test_temperature
79
111
  parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
80
112
  assert_equal(-17, parser.temperature.value)
@@ -91,6 +123,20 @@ class TestMetarParser < Test::Unit::TestCase
91
123
  assert_equal(:bar, parser.sea_level_pressure.options[:units])
92
124
  end
93
125
 
126
+ def test_remarks
127
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910 RMK AO2 P0000")
128
+ assert_instance_of(Array, parser.remarks)
129
+ assert_equal(2, parser.remarks.length)
130
+ assert_equal('AO2', parser.remarks[0])
131
+ assert_equal('P0000', parser.remarks[1])
132
+ end
133
+
134
+ def test_remarks_defaults_to_empty_array
135
+ parser = setup_parser('PAIL', "2010/02/06 16:10\nPAIL 061610Z 24006KT 1 3/4SM -SN BKN016 OVC030 M17/M20 A2910")
136
+ assert_instance_of(Array, parser.remarks)
137
+ assert_equal(0, parser.remarks.length)
138
+ end
139
+
94
140
  private
95
141
 
96
142
  def setup_parser(cccc, metar)
@@ -18,10 +18,19 @@ class TestMetarRaw < Test::Unit::TestCase
18
18
  end
19
19
  end
20
20
 
21
- def test_attributes
21
+ def test_cccc
22
22
  raw = Metar::Raw.new('LIRQ')
23
23
  assert_equal('LIRQ', raw.cccc)
24
+ end
25
+
26
+ def test_time
27
+ raw = Metar::Raw.new('LIRQ')
24
28
  assert_instance_of(Time, raw.time)
29
+ assert_equal(2010, raw.time.year)
30
+ end
31
+
32
+ def test_metar
33
+ raw = Metar::Raw.new('LIRQ')
25
34
  assert_instance_of(String, raw.metar)
26
35
  end
27
36
 
@@ -5,7 +5,11 @@ require File.dirname(__FILE__) + '/../metar_test_helper'
5
5
 
6
6
  class TestMetarReport < Test::Unit::TestCase
7
7
  def setup
8
- I18n.locale = :en
8
+ end
9
+
10
+ def test_name
11
+ report = setup_report('LIRQ', "2010/02/06 15:20\nLIRQ 061520Z 01007KT 350V050 9999 SCT035 BKN080 08/02 Q1005")
12
+ assert_equal('Firenze / Peretola', report.station_name)
9
13
  end
10
14
 
11
15
  def test_date
@@ -20,13 +24,12 @@ class TestMetarReport < Test::Unit::TestCase
20
24
 
21
25
  def test_wind_knots
22
26
  report = setup_report('LIRQ', "2010/02/06 15:20\nLIRQ 061520Z 01007KT 350V050 9999 SCT035 BKN080 08/02 Q1005")
23
- assert_equal('10°, 7 knots', report.wind)
24
- I18n.locale = :it
25
- assert_equal('10°, 7 nodi', report.wind)
27
+ assert_equal('13km/h N', report.wind)
26
28
  end
27
29
 
28
30
  def test_variable_wind
29
31
  report = setup_report('LIRQ', "2010/02/06 15:20\nLIRQ 061520Z 01007KT 350V050 9999 SCT035 BKN080 08/02 Q1005")
32
+ I18n.locale = :en
30
33
  assert_equal('350 degrees - 50 degrees', report.variable_wind)
31
34
  end
32
35
 
@@ -37,11 +40,15 @@ class TestMetarReport < Test::Unit::TestCase
37
40
 
38
41
  def test_runway_visible_range
39
42
  report = setup_report('ESSB', "2010/02/15 10:20\nESSB 151020Z 26003KT 2000 R12/1000N R30/1500N VV002 M07/M07 Q1013 1271//55")
43
+ I18n.locale = :en
40
44
  assert_equal('runway 12: 1000m, runway 30: 1500m', report.runway_visible_range)
45
+ I18n.locale = :it
46
+ assert_equal('pista 12: 1000m, pista 30: 1500m', report.runway_visible_range)
41
47
  end
42
48
 
43
49
  def test_runway_visible_range_variable
44
50
  report = setup_report('KPDX', "2010/02/15 11:08\nKPDX 151108Z 11006KT 1/4SM R10R/1600VP6000FT FG OVC002 05/05 A3022 RMK AO2")
51
+ I18n.locale = :en
45
52
  assert_equal('runway 10R: from 1600ft to more than 6000ft', report.runway_visible_range)
46
53
  end
47
54
 
@@ -80,6 +87,13 @@ class TestMetarReport < Test::Unit::TestCase
80
87
  assert_equal('1.00500 bar', report.sea_level_pressure)
81
88
  end
82
89
 
90
+ def test_to_s
91
+ report = setup_report('LIRQ', "2010/02/06 15:20\nLIRQ 061520Z 01007KT 350V050 9999 SCT035 BKN080 08/02 Q1005")
92
+ Metar::Report.attributes -= [:station_code, :variable_wind, :observer, :remarks]
93
+ I18n.locale = :en
94
+ assert_equal("name: Firenze / Peretola\ncountry: Italy\ntime: 15:20\nwind: 13km/h N\nvisibility: more than 10km\nsky: broken cloud\ntemperature: 8°C", report.to_s)
95
+ end
96
+
83
97
  private
84
98
 
85
99
  def setup_report(cccc, metar)
@@ -24,6 +24,26 @@ class TestStation < Test::Unit::TestCase
24
24
  assert_not_nil Metar::Station.find_by_cccc('LIRQ')
25
25
  end
26
26
 
27
+ def test_to_latitude_incorrect_gives_nil
28
+ assert_nil Metar::Station.to_latitude('23-15')
29
+ end
30
+
31
+ def test_to_latitude_n
32
+ assert_equal 43.8, Metar::Station.to_latitude('43-48N')
33
+ end
34
+
35
+ def test_to_latitude_s
36
+ assert_equal -23.25, Metar::Station.to_latitude('23-15S')
37
+ end
38
+
39
+ def test_to_longitude_e
40
+ assert_equal 11.2, Metar::Station.to_longitude('11-12E')
41
+ end
42
+
43
+ def test_to_longitude_w
44
+ assert_equal -11.2, Metar::Station.to_longitude('11-12W')
45
+ end
46
+
27
47
  def test_instantiation_sets_cccc
28
48
  station = Metar::Station.new('LIRQ')
29
49
  assert_equal 'LIRQ', station.cccc
@@ -40,29 +60,29 @@ class TestStation < Test::Unit::TestCase
40
60
  assert station.loaded?
41
61
  end
42
62
 
43
- def test_latitude_is_a_decimal_number
63
+ def test_name
44
64
  station = Metar::Station.new('LIRQ')
45
- assert station.latitude.to_s == station.latitude.to_f.to_s
65
+ assert_equal 'Firenze / Peretola', station.name
46
66
  end
47
67
 
48
- def test_longitude_is_a_decimal_number
68
+ def test_state
49
69
  station = Metar::Station.new('LIRQ')
50
- assert station.longitude.to_s == station.longitude.to_f.to_s
70
+ assert_equal '', station.state
51
71
  end
52
72
 
53
- def test_to_latitude_north
54
- assert(Metar::Station.to_latitude('43-48N') == 43.8)
73
+ def test_country
74
+ station = Metar::Station.new('LIRQ')
75
+ assert_equal 'Italy', station.country
55
76
  end
56
77
 
57
- def test_to_latitude_south
58
- assert(Metar::Station.to_latitude('43-48S') == -43.8)
78
+ def test_latitude_is_a_decimal_number
79
+ station = Metar::Station.new('LIRQ')
80
+ assert_equal station.latitude.to_s, station.latitude.to_f.to_s
59
81
  end
60
82
 
61
- def test_to_longitude_east
62
- assert(Metar::Station.to_longitude('011-12E') == 11.2)
83
+ def test_longitude_is_a_decimal_number
84
+ station = Metar::Station.new('LIRQ')
85
+ assert_equal station.longitude.to_s, station.longitude.to_f.to_s
63
86
  end
64
87
 
65
- def test_to_longitude_west
66
- assert(Metar::Station.to_longitude('011-12W') == -11.2)
67
- end
68
88
  end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 3
9
- version: 0.1.3
8
+ - 4
9
+ version: 0.1.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Joe Yates