# File rbot/utils.rb, line 363 def parse @decoded = Hash.new puts @input @input.split(" ").each {|part| if (part == 'METAR') # Type of Report: METAR @decoded['type'] = 'METAR' elsif (part == 'SPECI') # Type of Report: SPECI @decoded['type'] = 'SPECI' elsif (part == 'AUTO') # Report Modifier: AUTO @decoded['report_mod'] = 'AUTO' elsif (part == 'NIL') @nodata = true elsif (part =~ /^\S{4}$/ && ! (@decoded.has_key?('station'))) # Station Identifier @decoded['station'] = part elsif (part =~ /([0-9]{2})([0-9]{2})([0-9]{2})Z/) # ignore this bit, it's useless without month/year. some of these # things are hideously out of date. # now = Time.new # time = Time.gm(now.year, now.month, $1, $2, $3, 0) # Date and Time of Report # @decoded['time'] = time elsif (part == 'COR') # Report Modifier: COR @decoded['report_mod'] = 'COR' elsif (part =~ /([0-9]{3}|VRB)([0-9]{2,3}).*(KT|MPS|KMH)/) # Wind Group windunit = $3 # now do ereg to get the actual values part =~ /([0-9]{3}|VRB)([0-9]{2,3})((G[0-9]{2,3})?#{windunit})/ if ($1 == 'VRB') @decoded['wind_deg'] = 'variable directions' @decoded['wind_dir_text'] = 'variable directions' @decoded['wind_dir_text_short'] = 'VAR' else @decoded['wind_deg'] = $1 @decoded['wind_dir_text'] = @wind_dir_texts[($1.to_i/22.5).round] @decoded['wind_dir_text_short'] = @wind_dir_texts_short[($1.to_i/22.5).round] end store_speed($2, windunit, 'wind_meters_per_second', 'wind_knots', 'wind_miles_per_hour') if ($4 != nil) # We have a report with information about the gust. # First we have the gust measured in knots store_speed($4,windunit, 'wind_gust_meters_per_second', 'wind_gust_knots', 'wind_gust_miles_per_hour') end elsif (part =~ /([0-9]{3})V([0-9]{3})/) # Variable wind-direction @decoded['wind_var_beg'] = $1 @decoded['wind_var_end'] = $2 elsif (part == "9999") # A strange value. When you look at other pages you see it # interpreted like this (where I use > to signify 'Greater # than'): @decoded['visibility_miles'] = '>7'; @decoded['visibility_km'] = '>11.3'; elsif (part =~ /^([0-9]{4})$/) # Visibility in meters (4 digits only) # The visibility measured in kilometers, rounded to one decimal place. @decoded['visibility_km'] = sprintf("%.1f", $1.to_i / 1000) # The visibility measured in miles, rounded to one decimal place. @decoded['visibility_miles'] = sprintf("%.1f", $1.to_i / 1000 / 1.609344) elsif (part =~ /^[0-9]$/) # Temp Visibility Group, single digit followed by space @decoded['temp_visibility_miles'] = part elsif (@decoded['temp_visibility_miles'] && (@decoded['temp_visibility_miles']+' '+part) =~ /^M?(([0-9]?)[ ]?([0-9])(\/?)([0-9]*))SM$/) # Visibility Group if ($4 == '/') vis_miles = $2.to_i + $3.to_i/$5.to_i else vis_miles = $1.to_i; end if (@decoded['temp_visibility_miles'][0] == 'M') # The visibility measured in miles, prefixed with < to indicate 'Less than' @decoded['visibility_miles'] = '<' + sprintf("%.1f", vis_miles) # The visibility measured in kilometers. The value is rounded # to one decimal place, prefixed with < to indicate 'Less than' */ @decoded['visibility_km'] = '<' . sprintf("%.1f", vis_miles * 1.609344) else # The visibility measured in mile.s */ @decoded['visibility_miles'] = sprintf("%.1f", vis_miles) # The visibility measured in kilometers, rounded to one decimal place. @decoded['visibility_km'] = sprintf("%.1f", vis_miles * 1.609344) end elsif (part =~ /^(-|\+|VC|MI)?(TS|SH|FZ|BL|DR|BC|PR|RA|DZ|SN|SG|GR|GS|PE|IC|UP|BR|FG|FU|VA|DU|SA|HZ|PY|PO|SQ|FC|SS|DS)+$/) # Current weather-group @decoded['weather'] = '' unless @decoded.has_key?('weather') if (part[0].chr == '-') # A light phenomenon @decoded['weather'] += @strings['light'] part = part[1,part.length] elsif (part[0].chr == '+') # A heavy phenomenon @decoded['weather'] += @strings['heavy'] part = part[1,part.length] elsif (part[0,2] == 'VC') # Proximity Qualifier @decoded['weather'] += @strings['nearby'] part = part[2,part.length] elsif (part[0,2] == 'MI') @decoded['weather'] += @strings['mild'] part = part[2,part.length] else # no intensity code => moderate phenomenon @decoded['weather'] += @strings['moderate'] end while (part && bite = part[0,2]) do # Now we take the first two letters and determine what they # mean. We append this to the variable so that we gradually # build up a phrase. @decoded['weather'] += @weather_array[bite] # Here we chop off the two first letters, so that we can take # a new bite at top of the while-loop. part = part[2,-1] end elsif (part =~ /(SKC|CLR)/) # Cloud-layer-group. # There can be up to three of these groups, so we store them as # cloud_layer1, cloud_layer2 and cloud_layer3. @cloud_layers += 1; # Again we have to translate the code-characters to a # meaningful string. @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] = @cloud_condition_array[$1] @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_coverage'] = @cloud_coverage[$1] elsif (part =~ /^(VV|FEW|SCT|BKN|OVC)([0-9]{3})(CB|TCU)?$/) # We have found (another) a cloud-layer-group. There can be up # to three of these groups, so we store them as cloud_layer1, # cloud_layer2 and cloud_layer3. @cloud_layers += 1; # Again we have to translate the code-characters to a meaningful string. if ($3 == 'CB') # cumulonimbus (CB) clouds were observed. */ @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] = @cloud_condition_array[$1] + @strings['clouds_cb'] elsif ($3 == 'TCU') # towering cumulus (TCU) clouds were observed. @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] = @cloud_condition_array[$1] + @strings['clouds_tcu'] else @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_condition'] = @cloud_condition_array[$1] + @strings['clouds'] end @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_coverage'] = @cloud_coverage[$1] @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_altitude_ft'] = $2.to_i * 100 @decoded['cloud_layer'+ (@cloud_layers.to_s) +'_altitude_m'] = ($2.to_f * 30.48).round elsif (part =~ /^T([0-9]{4})$/) store_temp($1,'temp_c','temp_f') elsif (part =~ /^T?(M?[0-9]{2})\/(M?[0-9\/]{1,2})?$/) # Temperature/Dew Point Group # The temperature and dew-point measured in Celsius. @decoded['temp_c'] = sprintf("%d", $1.tr('M', '-')) if $2 == "//" || !$2 @decoded['dew_c'] = 0 else @decoded['dew_c'] = sprintf("%.1f", $2.tr('M', '-')) end # The temperature and dew-point measured in Fahrenheit, rounded to # the nearest degree. @decoded['temp_f'] = ((@decoded['temp_c'].to_f * 9 / 5) + 32).round @decoded['dew_f'] = ((@decoded['dew_c'].to_f * 9 / 5) + 32).round elsif(part =~ /A([0-9]{4})/) # Altimeter # The pressure measured in inHg @decoded['altimeter_inhg'] = sprintf("%.2f", $1.to_i/100) # The pressure measured in mmHg, hPa and atm @decoded['altimeter_mmhg'] = sprintf("%.1f", $1.to_f * 0.254) @decoded['altimeter_hpa'] = sprintf("%d", ($1.to_f * 0.33863881578947).to_i) @decoded['altimeter_atm'] = sprintf("%.3f", $1.to_f * 3.3421052631579e-4) elsif(part =~ /Q([0-9]{4})/) # Altimeter # This is strange, the specification doesnt say anything about # the Qxxxx-form, but it's in the METARs. # The pressure measured in hPa @decoded['altimeter_hpa'] = sprintf("%d", $1.to_i) # The pressure measured in mmHg, inHg and atm @decoded['altimeter_mmhg'] = sprintf("%.1f", $1.to_f * 0.7500616827) @decoded['altimeter_inhg'] = sprintf("%.2f", $1.to_f * 0.0295299875) @decoded['altimeter_atm'] = sprintf("%.3f", $1.to_f * 9.869232667e-4) elsif (part =~ /^T([0-9]{4})([0-9]{4})/) # Temperature/Dew Point Group, coded to tenth of degree. # The temperature and dew-point measured in Celsius. store_temp($1,'temp_c','temp_f') store_temp($2,'dew_c','dew_f') elsif (part =~ /^1([0-9]{4}$)/) # 6 hour maximum temperature Celsius, coded to tenth of degree store_temp($1,'temp_max6h_c','temp_max6h_f') elsif (part =~ /^2([0-9]{4}$)/) # 6 hour minimum temperature Celsius, coded to tenth of degree store_temp($1,'temp_min6h_c','temp_min6h_f') elsif (part =~ /^4([0-9]{4})([0-9]{4})$/) # 24 hour maximum and minimum temperature Celsius, coded to # tenth of degree store_temp($1,'temp_max24h_c','temp_max24h_f') store_temp($2,'temp_min24h_c','temp_min24h_f') elsif (part =~ /^P([0-9]{4})/) # Precipitation during last hour in hundredths of an inch # (store as inches) @decoded['precip_in'] = sprintf("%.2f", $1.to_f/100) @decoded['precip_mm'] = sprintf("%.2f", $1.to_f * 0.254) elsif (part =~ /^6([0-9]{4})/) # Precipitation during last 3 or 6 hours in hundredths of an # inch (store as inches) @decoded['precip_6h_in'] = sprintf("%.2f", $1.to_f/100) @decoded['precip_6h_mm'] = sprintf("%.2f", $1.to_f * 0.254) elsif (part =~ /^7([0-9]{4})/) # Precipitation during last 24 hours in hundredths of an inch # (store as inches) @decoded['precip_24h_in'] = sprintf("%.2f", $1.to_f/100) @decoded['precip_24h_mm'] = sprintf("%.2f", $1.to_f * 0.254) elsif(part =~ /^4\/([0-9]{3})/) # Snow depth in inches @decoded['snow_in'] = sprintf("%.2f", $1); @decoded['snow_mm'] = sprintf("%.2f", $1.to_f * 25.4) else # If we couldn't match the group, we assume that it was a # remark. @decoded['remarks'] = '' unless @decoded.has_key?("remarks") @decoded['remarks'] += ' ' + part; end } # Relative humidity # p @decoded['dew_c'] # 11.0 # p @decoded['temp_c'] # 21.0 # => 56.1 @decoded['rel_humidity'] = sprintf("%.1f",100 * (6.11 * (10.0**(7.5 * @decoded['dew_c'].to_f / (237.7 + @decoded['dew_c'].to_f)))) / (6.11 * (10.0 ** (7.5 * @decoded['temp_c'].to_f / (237.7 + @decoded['temp_c'].to_f))))) if @decoded.has_key?('dew_c') end