metar-parser 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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