/*
* Copyright 1998-2009 University Corporation for Atmospheric Research/Unidata
*
* Portions of this software were developed by the Unidata Program at the
* University Corporation for Atmospheric Research.
*
* Access and use of this software shall impose the following obligations
* and understandings on the user. The user is granted the right, without
* any fee or cost, to use, copy, modify, alter, enhance and distribute
* this software, and any derivative works thereof, and its supporting
* documentation for any purpose whatsoever, provided that this entire
* notice appears in all copies of the software, derivative works and
* supporting documentation. Further, UCAR requests that the user credit
* UCAR/Unidata in any publications that result from the use of this
* software or in any product that includes this software. The names UCAR
* and/or Unidata, however, may not be used in any advertising or publicity
* to endorse or promote any products or commercial entity unless specific
* written permission is obtained from UCAR/Unidata. The user also
* understands that UCAR/Unidata is not obligated to provide the user with
* any support, consulting, training or assistance of any kind with regard
* to the use, operation and performance of this software nor to provide
* the user with any updates, revisions, new versions or "bug fixes."
*
* THIS SOFTWARE IS PROVIDED BY UCAR/UNIDATA "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL UCAR/UNIDATA BE LIABLE FOR ANY SPECIAL,
* INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
* FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
* WITH THE ACCESS, USE OR PERFORMANCE OF THIS SOFTWARE.
*/
/*
* MetarParseReport
*
* parses one METAR report into it's variables
*
*/
package ucar.nc2.dt.point.decode;
import java.util.LinkedHashMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.IOException;
public class MetarParseReport {
/**
* Used to store fields values
**/
//private LinkedHashMap<String, String> field = new LinkedHashMap();
private LinkedHashMap field = new LinkedHashMap();
/**
* Used to store fields units
**/
//private HashMap<String, String> unit = new HashMap();
private HashMap unit = new HashMap();
public boolean parseReport(String input) {
field.clear();
unit.clear();
Matcher m;
float var1, var2, var3;
String report = null, remark = null;
String [] split;
// return if( /^\n/ ) ;
if (MP.B_CR.matcher(input).find()) {
return false;
}
// split input into report and remark to distinguish fields
split = MP.REMARKS.split(input);
report = split[ 0 ] +" ";
if( split.length == 2)
remark = " "+ split[ 1 ] +" ";
// $rep_type = $1 if( s#^(METAR|SPECI|TESTM|TESTS) ## ) ;
m = MP.B_metar.matcher(report);
if (m.find()) {
field.put("Report_Type", m.group(1));
report = m.replaceFirst("");
} else { // default
field.put("Report_Type", "METAR");
}
unit.put("Report_Type", "" );
// $stn_name = $1 if( s#^(\w4) ## ) ;
m = MP.station.matcher(report);
if (m.find()) {
field.put("Station", m.group(1));
unit.put("Station", "" );
report = m.replaceFirst(" ");
} else {
return false;
}
// all patterns from this point are embeded in spaces
// get day hour minute
// if( s#(\d2)(\d2)(\d2)Z## )
m = MP.ddhhmmZ.matcher(report);
if (m.find()) {
field.put("Day", m.group(1));
unit.put("Day", "" );
field.put("Hour", m.group(2));
unit.put("Hour", "" );
field.put("Minute", m.group(3));
unit.put("Minute", "" );
report = m.replaceFirst(" ");
} else {
return false;
}
// skip NIL reports
if (MP.NIL.matcher(report).find()) {
return false;
}
m = MP.COR.matcher(report);
if (m.find()) {
report = m.replaceFirst(" ");
}
// $AUTO = 1 if( s#AUTO\s+## ) ;
m = MP.AUTOS.matcher(report);
if (m.find()) {
field.put("AUTOS", "yes");
unit.put("AUTOS", "" );
report = m.replaceFirst(" ");
}
// get wind direction and speed
// if( s#(E|W|N|S)?(\d3|VRB)(\d2,3)(G)?(\d2,3)?(KMH|KT|MPS|MPH)\s+## )
m = MP.wind_direction_speed.matcher(report);
if (m.find()) {
// if( $2 eq "VRB" )
if (m.group(2).equals("VRB")) {
if( m.group(1) == null ) {
field.put("Variable_Wind_direction", "" );
} else {
field.put("Variable_Wind_direction", m.group(1));
}
unit.put("Variable_Wind_direction", "" );
} else {
// $DIR = $2 ;
field.put("Wind_Direction", m.group(2));
unit.put("Wind_Direction", "degrees" );
}
// $SPD = $3 ;
field.put("Wind_Speed", m.group(3));
// $GUST = $5 if( $4 eq "G" ) ;
if (m.group(4) != null && m.group(4).equals("G")) {
field.put("Wind_Gust", m.group(5));
}
// $UNITS = $6 ; need work if units != KT
unit.put("Wind_Speed", m.group(6));
unit.put("Wind_Gust", m.group(6));
report = m.replaceFirst(" ");
}
// get min|max wind direction
// if( s#^(\d3)V(\d3)\s+## )
m = MP.min_max_wind_dir.matcher(report);
if (m.find()) {
// $DIRmin = $1 ;
field.put("Wind_Direction_Min", m.group(1));
unit.put("Wind_Direction_Min", "degrees" );
// $DIRmax = $2 ;
field.put("Wind_Direction_Max", m.group(2));
unit.put("Wind_Direction_Max", "degrees" );
report = m.replaceFirst(" ");
}
// some reports use a place holder for visibility
// s#9999\s+## ;
report = MP.N9999.matcher(report).replaceFirst(" ");
// get visibility
boolean done = false;
// $prevail_VIS_SM = 0.0 if( s#M1/4SM\s+|<1/4SM\s+## ) ;
m = MP.visibilitySM.matcher(report);
if (m.find()) {
field.put("Visibility", "0.0");
unit.put("Visibility", "miles");
report = m.replaceFirst(" ");
done = true;
}
// $prevail_VIS_KM = 0.0 if( s#M1/4KM\s+|<1/4KM\s+## ) ;
if( ! done ) {
m = MP.visibilityKM.matcher(report);
if (m.find()) {
field.put("Visibility", "0.0");
unit.put("Visibility", "kilometer");
report = m.replaceFirst(" ");
done = true;
}
}
// if( s#(\d1,4) (\d1,3)/(\d1,3)(SM|KM)\s+## )
if( ! done ) {
m = MP.visibility1.matcher(report);
if (m.find()) {
// $prevail_VIS_SM = $1 + ( $2 / $3 ) if( $4 eq "SM" ) ;
var1 = Float.parseFloat(m.group(1));
var2 = Float.parseFloat(m.group(2));
var3 = Float.parseFloat(m.group(3));
var1 = var1 + (var2 / var3);
if (m.group(4).equals("SM")) {
field.put("Visibility", Float.toString(var1));
unit.put("Visibility", "miles");
// $prevail_VIS_KM = $1 + ( $2 / $3 ) if( $4 eq "KM" ) ;
} else {
field.put("Visibility", Float.toString(var1));
unit.put("Visibility", "kilometer");
}
report = m.replaceFirst(" ");
done = true;
}
}
// else( s#^(\d1,3)/(\d1,3)(KM|SM)\s+## )
if( ! done ) {
m = MP.visibility2.matcher(report);
if (m.find()) {
var1 = Float.parseFloat(m.group(1));
var2 = Float.parseFloat(m.group(2));
var1 = var1 / var2;
// $prevail_VIS_SM = $1 / $2 if( $3 eq "SM" ) ;
if (m.group(3).equals("SM")) {
field.put("Visibility", Float.toString(var1));
unit.put("Visibility", "miles");
// $prevail_VIS_KM = $1 / $2 if( $3 eq "KM" ) ;
} else {
field.put("Visibility", Float.toString(var1));
unit.put("Visibility", "kilometer");
}
report = m.replaceFirst(" ");
done = true;
}
}
// else( s# P?(\d1,4)(KM|SM)\s+## )
if( ! done ) {
m = MP.visibility3.matcher(report);
if (m.find()) {
// $prevail_VIS_SM = $1 if( $2 eq "SM" ) ;
if (m.group(2).equals("SM")) {
field.put("Visibility", m.group(1));
unit.put("Visibility", "miles");
// $prevail_VIS_KM = $1 if( $2 eq "KM" ) ;
} else {
field.put("Visibility", m.group(1));
unit.put("Visibility", "kilometer");
}
report = m.replaceFirst(" ");
done = true;
}
}
if( ! done ) {
// else( s# (\d4)((NE)|(NW)|(SE)|(SW)|(N)|(S)|(E)|(W))\s+## )
m = MP.visibility_direction.matcher(report);
if (m.find()) {
// $prevail_VIS_M = $1 ;
field.put("Visibility", m.group(1));
unit.put("Visibility", "meters");
// $VIS_dir = $2 ;
field.put("Visibility_Direction", m.group(2));
unit.put("Visibility_Direction", "");
report = m.replaceFirst(" ");
done = true;
}
}
// clear air
// $CAVOK = 1 if( s#CAVOK\s+## ) ;
m = MP.CAVOKS.matcher(report);
if (m.find()) {
field.put("Clear_Air", "yes");
unit.put("Clear_Air", "" );
report = m.replaceFirst(" ");
}
// runway decoding here
// $RVRNO = 1 if( s#RVRNO\s+## ) ;
m = MP.RVRNO.matcher(report);
if (m.find()) {
//field.put("RVRNOS", "");
field.put("RunwayReports", "No");
//unit.put("RVRNOS", "");
unit.put("RunwayReports", "");
report = m.replaceFirst(" ");
}
for (int i = 0; i < 4; i++) {
// if( s# R(\d2)(R|L|C)?/(M|P)?(\d1,4)V?(M|P)?(\d1,4)?(FT|N|D)?\s+## )
m = MP.runway.matcher(report);
if (m.find()) {
// $RV_designator[ $i ] = "$1$2" ;
String RV = "RV" + Integer.toString(i +1);
field.put(RV, m.group(1) );
unit.put(RV, "");
/*
field.put(RV, m.group(1) + m.group(2));
unit.put(RV, "");
// $RV_above_max[ $i ] = 1
// if( $3 eq "P" || $5 eq "P" ) ;
if ((m.group(3) != null && m.group(3).equals("P")) ||
(m.group(5) != null && m.group(5).equals("P"))) {
field.put(RV + "_Above_Max", "");
unit.put(RV + "_Above_Max", "");
}
// $RV_below_min[ $i ] = 1
// if( $3 eq "M" || $5 eq "M" ) ;
if ((m.group(3) != null && m.group(3).equals("M")) ||
(m.group(5) != null && m.group(5).equals("M"))) {
field.put(RV + "_Below_Min", "");
unit.put(RV + "_Below_Min", "");
}
// $RV_vrbl[ $i ] = 1 if( $6 ne "" ) ;
// if( $RV_vrbl[ $i ] )
// $RV_min[ $i ] = $4 * 1;
// $RV_max[ $i ] = $6 * 1;
if (m.group(6) != null) {
field.put(RV + "_Vrbl", "");
unit.put(RV + "_Vrbl", "");
field.put(RV + "_Min", m.group(4));
unit.put(RV + "_Min", "feet");
field.put(RV + "_Max", m.group(6));
unit.put(RV + "_Max", "feet");
} else {
// $RV_visRange[ $i ] = $4 * 1;
if(m.group(7) != null && m.group(7).equals( "FT")) {
field.put(RV + "_Visibility_Range", m.group(4));
unit.put(RV + "_Visibility_Range", "feet");
} else {
field.put(RV + "_Visibility_Range", m.group(4));
unit.put(RV + "_Visibility_Range", "");
}
}
*/
report = m.replaceFirst(" ");
} else {
break;
}
} // end runway decoding
// Get weather conditions
// code table 4678
done = true;
StringBuilder WX = new StringBuilder();
for (int i = 0; i < 4; i++) {
// if( s#(\+|-|VC|PR| )(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)## )
m = MP.WeatherPrecip.matcher(report);
//System.out.println( "before if report ="+ report );
if (m.find()) {
done = false;
//System.out.println( "after if report ="+ report );
//if (! m.group(1).equals( " " )) {
WX.append( m.group(1) );
//}
if (m.group(2) != null) {
WX.append( m.group(2) );
}
WX.append( m.group(3) );
report = m.replaceFirst(" ");
}
// if( s#(\+|-|VC|PR| )(MI|BC|DR|BL|SH|TS|FZ)?(BR|FG|FU|VA|DU|SA|HZ|PY)## )
m = MP.WeatherObs.matcher(report);
if (m.find()) {
done = false;
//System.out.println( "after if report ="+ report );
//if (! m.group(1).equals( " " )) {
WX.append( m.group(1) );
//}
if (m.group(2) != null) {
WX.append( m.group(2) );
}
WX.append( m.group(3) );
report = m.replaceFirst(" ");
}
// if( s#(\+|-|VC|PR| )(MI|BC|DR|BL|SH|TS|FZ)?(PO|SQ|FC|SS|DS)## )
m = MP.WeatherOther.matcher(report);
if (m.find()) {
done = false;
//System.out.println( "after if report ="+ report );
//if (! m.group(1).equals( " " )) {
WX.append( m.group(1) );
//}
if (m.group(2) != null) {
WX.append( m.group(2) );
}
WX.append( m.group(3) );
report = m.replaceFirst(" ");
}
if( done )
break;
done = true;
WX.append( " " );
}
if (WX.length() > 0) {
WX.setLength( WX.length() -1 );
field.put("Weather", WX.toString() );
unit.put("Weather", "");
}
//System.out.println( "after if report ="+ report );
// Interpret cloud conditions
// $cloud_type[ 0 ] = $1 if( s#(CLR|SKC)\s+## ) ;
m = MP.CLR_or_SKC.matcher(report);
if (m.find()) {
field.put("Cloud_Type", m.group(1));
unit.put("Cloud_Type", "");
report = m.replaceFirst(" ");
}
// $vert_VIS = cloud_hgt2_meters( $1 ) if( s#^VV(\d3)\s+## ) ;
m = MP.vertical_VIS.matcher(report);
if (m.find()) {
field.put("Vertical_Visibility", cloud_hgt2_meters(m.group(1)));
unit.put("Vertical_Visibility", "meters" );
report = m.replaceFirst(" ");
}
// cloud layers up to 6
for (int i = 0; i < 6; i++) {
// if( s# (\+|-)?(OVC|SCT|FEW|BKN)(\d3)(\w1,3)?\s+## )
m = MP.cloud_cover.matcher(report);
if (m.find()) {
String cloud = "Cloud_Layer_" + Integer.toString(i + 1);
if (m.group(1) == null) {
field.put(cloud + "_Type", m.group(2));
} else {
field.put(cloud + "_Type", m.group(1) + m.group(2));
}
unit.put(cloud + "_Type", "");
// just report meters
// $cloud_hgt[ $i ] = $3 * 100 ;
//field.put(cloud + "_Height", Integer.toString(Integer.parseInt(m.group(3)) * 100));
//unit.put(cloud + "_Height", "feet");
// $cloud_meters[ $i ] = cloud_hgt2_meters( $3 ) ;
field.put(cloud + "_Height", cloud_hgt2_meters(m.group(3)));
unit.put(cloud + "_Height", "meters");
// $cloud_phenom[ $i ] = padstr( $4, 4 ) if( $4 ) ;
if (m.group(4) != null) {
field.put(cloud + "_Phenom", m.group(4));
unit.put(cloud + "_Phenom", "");
}
report = m.replaceFirst(" ");
} else {
break;
}
} // end clouds
// Temperature and Dew Point, try temp tenths first
float air_temperature = -999;
float dew_point_temperature = -999;
// if( s#T(0|1)(\d3)(0|1)?(\d3)?\s+## )
if( remark != null)
m = MP.Temperature_tenths.matcher(remark);
if ( remark != null && m.find() ) {
// if( $1 == 0 )
// $T_tenths = 0.1 * $2 ;
// else
// $T_tenths = -0.1 * $2 ;
//
air_temperature = (float)(Float.parseFloat(m.group(2)) * .1);
if (m.group(1).equals("1")) {
//T = "-" + T;
air_temperature *= -1;
}
field.put("Temperature", Float.toString( air_temperature ) );
unit.put("Temperature", "Celsius");
// if( defined( $3 ) && $3 == 0 )
// $TD_tenths = 0.1 * $4 ;
// elsif( defined( $3 ) && $3 == 1 )
// $TD_tenths = -0.1 * $4 ;
//
if (m.group(3) != null) {
dew_point_temperature = (float)(Float.parseFloat(m.group(4)) * .1);
// $TD *= -1 if( $3 ) ;
if (m.group(3).equals("1")) {
//TD = "-" + TD;
dew_point_temperature *= -1;
}
field.put("DewPoint", Float.toString( dew_point_temperature ));
unit.put("DewPoint", "Celsius");
}
remark = m.replaceFirst(" ");
} else { // check for coarse temperature
// get temperature and dew point
// if( s#^(M)?(\d2)/(M)?(\d2)?\s+## )
m = MP.Temperature.matcher(report);
if (m.find()) {
// $T = $2 ;
//String T = m.group(2);
air_temperature = Float.parseFloat(m.group(2));
// $T *= -1 if( $1 ) ;
//if( m.group( 1 ).equals( "M" ) )
if (m.group(1) != null) {
//T = "-" + T;
air_temperature *= -1;
}
field.put("Temperature", Float.toString( air_temperature ) );
unit.put("Temperature", "Celsius");
// $TD = $4 if( defined( $4 ) ) ;
if (m.group(4) != null) {
dew_point_temperature = Float.parseFloat(m.group(4));
// $TD *= -1 if( $3 ) ;
if (m.group(3) != null) {
//TD = "-" + TD;
dew_point_temperature *= -1;
}
field.put("DewPoint", Float.toString( dew_point_temperature ));
unit.put("DewPoint", "Celsius");
}
report = m.replaceFirst(" ");
} // end T and TD
}
// get Altimeter settings
// if( s# (A|Q)(\d4\.?\d?)\s+## )
m = MP.altimeter.matcher(report);
if (m.find()) {
// if( $1 eq "A" )
if (m.group(1).equals("A")) {
// $inches_ALTIM = $2 * 0.01 ;
field.put("Altimeter", Double.toString(Float.parseFloat(m.group(2)) * 0.01));
unit.put("Altimeter", "inches");
} else {
// $hectoPasc_ALTIM = $2 ;
field.put("Altimeter", m.group(2));
unit.put("Altimeter", "hectopascal");
}
report = m.replaceFirst(" ");
}
// $NOSIG = 1 if( s#NOSIG## ) ;
m = MP.NOSIG.matcher(report);
if (m.find()) {
field.put("Weather", "No");
unit.put("Weather", "");
report = m.replaceFirst(" ");
}
// check for remarks or done
if( remark == null)
return true;
// process remarks now, looking for most used ones first
// get Automated reports
// if( s#(A01|A01A|A02|A02A|AO1|AO1A|AO2|AO2A|AOA)\s+## ) ;
m = MP.automatic_report.matcher(remark);
if (m.find()) {
field.put("Automatic_Report", m.group(1));
unit.put("Automatic_Report", "");
remark = m.replaceFirst(" ");
}
// check if no more info in report
if (MP.spaces.matcher(remark).matches()) {
return true;
}
// Sea-Level presure not available
//$SLPNO = 1 if( s# SLPNO\s+## ) ;
m = MP.SLPNO.matcher(remark);
if (m.find()) {
//field.put("SLPNO", "yes");
//unit.put("SLPNO", "");
field.put("Sea_Level_Pressure_available", "No");
unit.put("Sea_Level_Pressure_available", "");
remark = m.replaceFirst(" ");
}
//if( s# SLP\s?(\d3)\s+## )
m = MP.SLP.matcher(remark);
if (m.find()) {
float slp;
// if( $1 >= 550 )
if (Integer.parseInt(m.group(1)) >= 550) {
// $SLP = $1 / 10. + 900. ;
field.put("Sea_Level_Pressure", Double.toString(Float.parseFloat(m.group(1)) * 0.1 + 900));
} else {
// $SLP = $1 / 10. + 1000. ;
field.put("Sea_Level_Pressure", Double.toString(Float.parseFloat(m.group(1)) * 0.1 + 1000));
}
unit.put("Sea_Level_Pressure", "hectopascal");
remark = m.replaceFirst(" ");
}
// check if no more info in report
if (MP.spaces.matcher(remark).matches()) {
return true;
}
// Hourly precipitation amount
// $PRECIP_hourly = $1 / 100 if( s#P ?(\d1,5)\s+## ) ;
m = MP.hourly_precip.matcher(remark);
if (m.find()) {
field.put("Hourly_Precipitation", Double.toString(Float.parseFloat(m.group(1)) * .01));
unit.put("Hourly_Precipitation", "inches");
remark = m.replaceFirst(" ");
}
// check if no more info in report
if (MP.spaces.matcher(remark).matches()) {
return true;
}
// precipitation sensor not working PWINO
//$PWINO = 1 if( s#PWINO\s+## ) ;
m = MP.PWINO.matcher(remark);
if (m.find()) {
//field.put("PWINO", "");
//unit.put("PWINO", "");
field.put("PRECIP_sensor_working", "No");
unit.put("PRECIP_sensor_working", "");
remark = m.replaceFirst(" ");
}
// check if no more info in report
if (MP.spaces.matcher(remark).matches()) {
return true;
}
// Lightning detection sensor not working TSNO
// $TSNO = 1 if( s#TSNO\s+## ) ;
m = MP.TSNO.matcher(remark);
if (m.find()) {
//field.put("TSNO", "yes");
//unit.put("TSNO", "");
field.put("Lightning_sensor_working", "No");
unit.put("Lightning_sensor_working", "");
remark = m.replaceFirst(" ");
}
// check if no more info in report
if (MP.spaces.matcher(remark).matches()) {
return true;
}
// get Tornado data if present
// if( s#(TORNADO\w0,2|WATERSPOUTS*|FUNNEL CLOUDS*)\s+## )
m = MP.tornado.matcher(remark);
if (m.find()) {
field.put("TornadicType", m.group(1));
unit.put("TornadicType", "");
remark = m.replaceFirst(" ");
// if( s#(B|E)(\d\d)(\d\d)?\s+## )
m = MP.tornadoTime.matcher(remark);
if (m.find()) {
String time;
String units;
if(m.group(2) == null ) {
time = m.group(3);
units = "mm";
} else {
time = m.group(2) + m.group(3);
units = "hhmm";
}
// if( $1 eq "B" )
if (m.group(1).equals("B")) {
// $BTornadic_hh = $2 ;
// $BTornadic_mm = $3 ;
field.put("Begin_Tornado", time);
unit.put("Begin_Tornado", units);
} else {
// $ETornadic_hh = $2 ;
// $ETornadic_mm = $3 if( defined( $3 ) ) ;
field.put("End_Tornado", time);
unit.put("End_Tornado", units);
}
remark = m.replaceFirst(" ");
}
// $TornadicLOC = padstr( $1, 10 )
// if( s#^(DSNT|VCY STN|VC STN|VCY|VC)\s+## ) ;
m = MP.tornadoLocation.matcher(remark);
if (m.find()) {
field.put("Tornado_Location", m.group(1));
unit.put("Tornado_Location", "");
remark = m.replaceFirst(" ");
}
// $TornadicDIR = padstr( $1, 2 )
// if( s#^(NE|NW|SE|SW|N|S|E|W)\s+## ) ;
m = MP.tornadoDirection.matcher(remark);
if (m.find()) {
field.put("Tornado_Direction", m.group(1));
unit.put("Tornado_Direction", "");
remark = m.replaceFirst(" ");
}
} // end tornado
// get Peak winds
// if( s#PK WND (\d3)(\d1,3)/(\d\d)?(\d\d)\s+## )
m = MP.peakWind.matcher(remark);
if (m.find()) {
// $PKWND_dir = $1 ;
field.put("Peak_Wind_Direction", m.group(1));
unit.put("Peak_Wind_Direction", "degrees");
// $PKWND_spd = $2 ;
field.put("Peak_Wind_Speed", m.group(2));
unit.put("Peak_Wind_Speed", "knots");
// $PKWND_hh = $3 if( defined( $3 ) ) ;
// $PKWND_mm = $4 ;
String time;
String units;
if(m.group(3) == null ) {
time = m.group(4);
units = "mm";
} else {
time = m.group(3) + m.group(4);
units = "hhmm";
}
field.put("Peak_Wind_Time", time );
unit.put("Peak_Wind_Time", units );
remark = m.replaceFirst(" ");
}
// get Wind shift
// if( s#WSHFT (\d\d)?(\d\d)\s+## )
m = MP.windShift.matcher(remark);
if (m.find()) {
// $WshfTime_hh = $1 if( defined( $1 ) );
// $WshfTime_mm = $2 ;
String time;
String units;
if(m.group(1) == null ) {
time = m.group(2);
units = "mm";
} else {
time = m.group(1) + m.group(2);
units = "hhmm";
}
field.put("Wind_Shift", time);
unit.put("Wind_Shift", units);
remark = m.replaceFirst(" ");
}
// get FROPO ( wind shift because of frontal passage )
// $Wshft_FROPA = 1 if( s#FROPA\s+## ) ;
m = MP.FROPA.matcher(remark);
if (m.find()) {
field.put("Wind_Shift_Frontal_Passage", "Yes");
unit.put("Wind_Shift_Frontal_Passage", "");
remark = m.replaceFirst(" ");
}
// Tower visibility
// if( s#TWR (VIS|VSBY) (\d1,3) (\d1,2)/(\d1,2)\s+## )
// $VIS_TWR = $2 + ( $3 / $4 ) ;
m = MP.towerVisibility1.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var3 = Float.parseFloat(m.group(4));
var1 = var1 + (var2 / var3);
field.put("Tower_Visibility", Float.toString(var1));
unit.put("Tower_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s#TWR (VIS|VSBY) (\d1,2)/(\d1,2)\s+## )
// $VIS_TWR = ( $2 / $3 ) ;
} else {
m = MP.towerVisibility2.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var1 = var1 / var2;
field.put("Tower_Visibility", Float.toString(var1));
unit.put("Tower_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s#TWR (VIS|VSBY) (\d1,3)\s+## )
// $VIS_TWR = $2 ;
} else {
m = MP.towerVisibility3.matcher(remark);
if (m.find()) {
field.put("Tower_Visibility", m.group(2));
unit.put("Tower_Visibility", "miles");
remark = m.replaceFirst(" ");
}
}
}
// Surface visibility
// if( s# SFC (VIS|VSBY) (\d1,3) (\d1,2)/(\d1,2)\s+## )
// $VIS_SFC = $2 + ( $3 / $4 ) ;
m = MP.surfaceVisibility1.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var3 = Float.parseFloat(m.group(4));
var1 = var1 + (var2 / var3);
field.put("Surface_Visibility", Float.toString(var1));
unit.put("Surface_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s# SFC (VIS|VSBY) (\d1,2)/(\d1,2)\s+## )
// $VIS_SFC = ( $2 / $3 ) ;
} else {
m = MP.surfaceVisibility2.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var1 = var1 / var2;
field.put("Surface_Visibility", Float.toString(var1));
unit.put("Surface_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s# SFC (VIS|VSBY) (\d1,3)\s+## )
// $VIS_SFC = $2 ;
} else {
m = MP.surfaceVisibility3.matcher(remark);
if (m.find()) {
field.put("Surface_Visibility", m.group(2));
unit.put("Surface_Visibility", "miles");
remark = m.replaceFirst(" ");
}
}
}
// Variable visibility
// if( s#(VIS|VSBY) (\d1,3) (\d1,2)/(\d1,2)V(\d1,3) (\d1,2)/(\d1,2)\s+## )
// $VISmin = $2 + ( $3 / $4 ) ;
// $VISmax = $5 + ( $6 / $7 ) ;
m = MP.variableVisibility1.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var3 = Float.parseFloat(m.group(4));
var1 = var1 + (var2 / var3);
field.put("Variable_Visibility_Min", Float.toString(var1));
unit.put("Variable_Visibility_Min", "miles");
var1 = Float.parseFloat(m.group(5));
var2 = Float.parseFloat(m.group(6));
var3 = Float.parseFloat(m.group(7));
var1 = var1 + (var2 / var3);
field.put("Variable_Visibility_Max", Float.toString(var1));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,3)V(\d1,3) (\d1,2)/(\d1,2)\s+## )
// $VISmin = $2 ;
// $VISmax = $3 + ( $4 / $5 ) ;
} else {
m = MP.variableVisibility2.matcher(remark);
if (m.find()) {
field.put("Variable_Visibility_Min", m.group(2));
unit.put("Variable_Visibility_Min", "miles");
var1 = Float.parseFloat(m.group(3));
var2 = Float.parseFloat(m.group(4));
var3 = Float.parseFloat(m.group(5));
var1 = var1 + (var2 / var3);
field.put("Variable_Visibility_Max", Float.toString(var1));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,2)/(\d1,2)V(\d1,3) (\d1,2)/(\d1,2)\s+## )
// $VISmin = ( $2 / $3 ) ;
// $VISmax = $4 + ( $5 / $6 ) ;
} else {
m = MP.variableVisibility3.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var1 = var1 / var2;
field.put("Variable_Visibility_Min", Float.toString(var1));
unit.put("Variable_Visibility_Min", "miles");
var1 = Float.parseFloat(m.group(4));
var2 = Float.parseFloat(m.group(5));
var3 = Float.parseFloat(m.group(6));
var1 = var1 + (var2 / var3);
field.put("Variable_Visibility_Max", Float.toString(var1));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,3) (\d1,2)/(\d1,2)V(\d1,3)\s+## )
// $VISmin = $2 + ( $3 / $4 ) ;
// $VISmax = $5 ;
} else {
m = MP.variableVisibility4.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var3 = Float.parseFloat(m.group(4));
var1 = var1 + (var2 / var3);
field.put("Variable_Visibility_Min", Float.toString(var1));
unit.put("Variable_Visibility_Min", "miles");
field.put("Variable_Visibility_Max", m.group(5));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,3)V(\d1,3)\s+## )
// $VISmin = $2 ;
// $VISmax = $3 ;
} else {
m = MP.variableVisibility5.matcher(remark);
if (m.find()) {
field.put("Variable_Visibility_Min", m.group(2));
unit.put("Variable_Visibility_Min", "miles");
field.put("Variable_Visibility_Max", m.group(3));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,2)/(\d1,2)V(\d1,3)\s+## )
// $VISmin = ( $2 / $3 ) ;
// $VISmax = $4 ;
} else {
m = MP.variableVisibility6.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var1 = var1 / var2;
field.put("Variable_Visibility_Min", Float.toString(var1));
unit.put("Variable_Visibility_Min", "miles");
field.put("Variable_Visibility_Max", m.group(4));
unit.put("Variable_Visibility_Max", "miles");
remark = m.replaceFirst(" ");
}
}
}
}
}
} // end variableVisibility
// Second site visiblity
// if( s#(VIS|VSBY) (\d1,3) (\d1,2)/(\d1,2) (RY\d1,2)\s+## )
// $VIS_2ndSite = $2 + ( $3 / $4 ) ;
// $VIS_2ndSite_LOC = padstr( $5, 10 ) ;
m = MP.Visibility2ndSite1.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var3 = Float.parseFloat(m.group(4));
var1 = var1 + (var2 / var3);
field.put("Second_Site_Visibility", Float.toString(var1));
unit.put("Second_Site_Visibility", "miles");
field.put("Second_Site_Location", m.group(5));
unit.put("Second_Site_Location", "");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,3) (RY\d1,2)\s+## )
// $VIS_2ndSite = $2 ;
// $VIS_2ndSite_LOC = padstr( $3, 10 ) ;
} else {
m = MP.Visibility2ndSite2.matcher(remark);
if (m.find()) {
field.put("Second_Site_Visibility", m.group(2));
unit.put("Second_Site_Visibility", "miles");
field.put("Second_Site_Location", m.group(3));
unit.put("Second_Site_Location", "");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (\d1,2)/(\d1,2) (RY\d1,2)\s+## )
// $VIS_2ndSite = ( $2 / $3 ) ;
// $VIS_2ndSite_LOC = padstr( $4, 10 ) ;
} else {
m = MP.Visibility2ndSite3.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(2));
var2 = Float.parseFloat(m.group(3));
var1 = var1 / var2;
field.put("Second_Site_Visibility", Float.toString(var1));
unit.put("Second_Site_Visibility", "miles");
field.put("Second_Site_Location", m.group(4));
unit.put("Second_Site_Location", "");
remark = m.replaceFirst(" ");
}
}
} // end Second site visiblity
/* let lighning go to extra fields cuz convnetion not followed
// Lightning data ( Occasional,Frequent,Continuous) and
// (Cloud-Ground,In-Cloud,Cloud-Cloud,Cloud-Air)
// if( s# (OCNL|FRQ|CNS) LTG\s?(CG|IC|CC|CA)\s?(DSNT|AP|VCY STN|VCNTY STN)?\s?(NE|NW|SE|SW|N|S|E|W)?\s+## )
m = MP.Lightning.matcher(remark);
if (m.find()) {
// $LTG_OCNL = 1 if( $1 eq "OCNL" ) ;
// $LTG_FRQ = 1 if( $1 eq "FRQ" ) ;
// $LTG_CNS = 1 if( $1 eq "CNS" ) ;
// $LTG_CG = 1 if( $2 eq "CG" ) ;
// $LTG_IC = 1 if( $2 eq "IC" ) ;
// $LTG_CC = 1 if( $2 eq "CC" ) ;
// $LTG_CA = 1 if( $2 eq "CA" ) ;
// $LTG_DSNT = 1 if( $3 eq "DSNT" ) ;
// $LTG_AP = 1 if( $3 eq "AP" ) ;
// $LTG_VcyStn = 1 if( $3 eq "VCY STN" || $3 eq "VCNTY STN" ) ;
// $LTG_DIR = padstr( $4, 2 ) if( defined( $4 ) ) ;
field.put("Lightning", m.group(1));
unit.put("Lightning", "");
remark = m.replaceFirst(" ");
} // end Lightning data
*/
// get min/max for Variable Ceiling
// if( s#CIG (\d1,4)V(\d1,4)\s+## )
// $Ceiling_min = $1 ;
// $Ceiling_max = $2 ;
m = MP.CIG.matcher(remark);
if (m.find()) {
field.put("Ceiling_Min", Integer.toString(Integer.parseInt(m.group(1)) * 100));
unit.put("Ceiling_Min", "feet");
field.put("Ceiling_Max", Integer.toString(Integer.parseInt(m.group(2)) * 100));
unit.put("Ceiling_Max", "feet");
remark = m.replaceFirst(" ");
}
// ? about SKY condition at 2nd location
// get 2nd site ceiling and location
// if( s#CIG (\d3) (RY\d1,2)\s+## )
// $CIG_2ndSite_meters = $1 * 10 ;
// $CIG_2ndSite_LOC = $2 ;
m = MP.CIG_RY.matcher(remark);
if (m.find()) {
var1 = Float.parseFloat(m.group(1)) * 10;
field.put("Second_Site_Sky", Float.toString(var1));
unit.put("Second_Site_Sky", "feet");
field.put("Second_Site_Sky_Location", m.group(2));
unit.put("Second_Site_Sky_Location", "");
remark = m.replaceFirst(" ");
}
// Presure falling rapidly
// $PRESFR = 1 if( s#PRESFR/?\s+## ) ;
m = MP.PRESFR.matcher(remark);
if (m.find()) {
field.put("Pressure_Falling_Rapidly", "Yes");
unit.put("Pressure_Falling_Rapidly", "");
remark = m.replaceFirst(" ");
}
// Presure rising rapidly
// $PRESRR = 1 if( s#PRESRR/?\s+## ) ;
m = MP.PRESRR.matcher(remark);
if (m.find()) {
field.put("Pressure_Rising_Rapidly", "Yes");
unit.put("Pressure_Rising_Rapidly", "");
remark = m.replaceFirst(" ");
}
// Sector visibility
// if( s# (VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d1,3) (\d1,2)/(\d1,2)\s+## )
// $SectorVIS_DIR = padstr( $2, 2 ) ;
// $SectorVIS = $3 + ( $4 / $5 ) ;
m = MP.sectorVisibility1.matcher(remark);
if (m.find()) {
field.put("Sector_Visibility_Direction", m.group(2));
unit.put("Sector_Visibility_Direction", "");
var1 = Float.parseFloat(m.group(3));
var2 = Float.parseFloat(m.group(4));
var3 = Float.parseFloat(m.group(5));
var1 = var1 + (var2 / var3);
field.put("Sector_Visibility", Float.toString(var1));
unit.put("Sector_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W) (\d1,2)/(\d1,2)\s+## )
// $SectorVIS_DIR = padstr( $2, 2 ) ;
// $SectorVIS = ( $3 / $4 ) ;
} else {
m = MP.sectorVisibility2.matcher(remark);
if (m.find()) {
field.put("Sector_Visibility_Direction", m.group(2));
unit.put("Sector_Visibility_Direction", "");
var1 = Float.parseFloat(m.group(3));
var2 = Float.parseFloat(m.group(4));
var1 = var1 / var2;
field.put("Sector_Visibility", Float.toString(var1));
unit.put("Sector_Visibility", "miles");
remark = m.replaceFirst(" ");
// elsif( s#(VIS|VSBY) (NE|NW|SE|SW|N|S|E|W)(\d1,3)\s+## )
// $SectorVIS_DIR = padstr( $2, 2 ) ;
// $SectorVIS = $3 ;
} else {
m = MP.sectorVisibility3.matcher(remark);
if (m.find()) {
field.put("Sector_Visibility_Direction", m.group(2));
unit.put("Sector_Visibility_Direction", "");
field.put("Sector_Visibility", m.group(3));
unit.put("Sector_Visibility", "miles");
remark = m.replaceFirst(" ");
}
}
}
// Hailstone activity and size
// if( s# GR M1/4\s+## )
// $GR = 1 ;
// $GRsize = 1 / 8 ;
m = MP.GR1.matcher(remark);
if (m.find()) {
field.put("Hailstone_Activity", "yes");
unit.put("Hailstone_Activity", "");
field.put("Hailstone_Size", "0.25");
unit.put("Hailstone_Size", "");
remark = m.replaceFirst(" ");
// elsif( s# GR (\d1,3) (\d1,2)/(\d1,2)\s+## )
// $GR = 1 ;
// $GRsize = $1 + ( $2 / $3 ) ;
} else {
m = MP.GR2.matcher(remark);
if (m.find()) {
field.put("Hailstone_Activity", "yes");
unit.put("Hailstone_Activity", "");
var1 = Float.parseFloat(m.group(1));
var2 = Float.parseFloat(m.group(2));
var3 = Float.parseFloat(m.group(3));
var1 = var1 + (var2 / var3);
field.put("Hailstone_Size", Float.toString(var1));
unit.put("Hailstone_Size", "");
remark = m.replaceFirst(" ");
// elsif( s# GR (\d1,2)/(\d1,2)\s+## )
// $GR = 1 ;
// $GRsize = ( $1 / $2 ) ;
} else {
m = MP.GR3.matcher(remark);
if (m.find()) {
field.put("Hailstone_Activity", "yes");
unit.put("Hailstone_Activity", "");
var1 = Float.parseFloat(m.group(1));
var2 = Float.parseFloat(m.group(2));
var1 = var1 / var2;
field.put("Hailstone_Size", Float.toString(var1));
unit.put("Hailstone_Size", "");
remark = m.replaceFirst(" ");
// elsif( s#GR (\d1,3)\s+## )
// $GR = 1 ;
// $GRsize = $1 ;
} else {
m = MP.GR4.matcher(remark);
if (m.find()) {
field.put("Hailstone_Activity", "yes");
unit.put("Hailstone_Activity", "");
field.put("Hailstone_Size", m.group(1));
unit.put("Hailstone_Size", "");
remark = m.replaceFirst(" ");
}
}
}
}
// $GR = 1 if( s# GS\s+## ) ;
m = MP.GR.matcher(remark);
if (m.find()) {
field.put("Hailstone_Activity", "yes");
unit.put("Hailstone_Activity", "");
remark = m.replaceFirst(" ");
}
// VIRGA activity
// if( s#VIRGA (DSNT )?(NE|NW|SE|SW|N|S|E|W)?\s+## )
// $VIRGA = 1 ;
// $VIRGAdir = padstr( $2, 2 ) if( $2 ) ;
m = MP.VIRGA.matcher(remark);
if (m.find()) {
field.put("Virga_Activity", "yes");
unit.put("Virga_Activity", "");
if( m.group(1) != null ) {
field.put("Virga_Direction", m.group(1));
unit.put("Virga_Direction", "");
}
if( m.group(2) != null ) {
field.put("Virga_Direction", m.group(2));
unit.put("Virga_Direction", "");
}
remark = m.replaceFirst(" ");
}
// Surface-based Obscuring Phenomena SfcObscuration weather conditions
// code table 4678
// if( s#-X(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(\d)\s+## )
// $SfcObscuration = padstr( "$1$2$3$4$5", 8 ) ;
// $OctsSkyObscured = $6 ;
/* not coded to current implementation, so let it go to plain lang remarks
m = MP.obscuring.matcher(remark);
if (m.find()) {
String tmp = "";
if (m.group(1) != null) {
tmp = m.group(1);
}
if (m.group(2) != null) {
tmp = m.group(2);
}
if (m.group(3) != null) {
tmp = m.group(3);
}
if (m.group(4) != null) {
tmp = m.group(4);
}
if (m.group(5) != null) {
tmp = m.group(5);
}
if ( ! tmp.equals("")) {
field.put("Surface_Obscuration", tmp );
unit.put("Surface_Obscuration", "" );
}
field.put("OctsSkyObscured", m.group(6));
unit.put("OctsSkyObscured", "");
remark = m.replaceFirst(" ");
}
*/
// get Ceiling_est or Ceiling height
// $CIGNO = 1 if( s#CIGNO\s+## ) ;
m = MP.CIGNO.matcher(remark);
if (m.find()) {
//field.put("CIGNO", "");
//unit.put("CIGNO", "");
field.put("Ceiling_height_available", "No");
unit.put("Ceiling_height_available", "");
remark = m.replaceFirst(" ");
}
// if( s#CIG(E)?(\d3)\s+## )
// if( $1 eq "E" )
// $Ceiling_est = $2 * 100 ;
// else
// $Ceiling = $2 * 100 ;
m = MP.CIG_EST.matcher(remark);
if (m.find()) {
String est = Integer.toString(Integer.parseInt(m.group(2)) * 100);
//if (m.group(1).equals("E")) {
//field.put("Ceiling_Estimate", est);
//unit.put("Ceiling_Estimate", "feet");
//else {
field.put("Ceiling", est);
unit.put("Ceiling", "feet");
//
remark = m.replaceFirst(" ");
}
// Variable Sky conditions
// if( s#(FEW|SCT|BKN|OVC)(\d3)? V (FEW|SCT|BKN|OVC)\s+## )
// $VrbSkyBelow = $1 ;
// $VrbSkyLayerHgt = $2 * 100 if( defined( $2 ) ) ;
// $VrbSkyAbove = $3 ;
m = MP.variableSky.matcher(remark);
if (m.find()) {
field.put("Variable_Sky_Below", m.group(1));
unit.put("Variable_Sky_Below", "feet");
if (m.group(2) != null) {
field.put("Variable_Sky_Height", Integer.toString(Integer.parseInt(m.group(2)) * 100));
unit.put("Variable_Sky_Height", "feet");
}
field.put("Variable_Sky_Above", m.group(3));
unit.put("Variable_Sky_Above", "feet");
remark = m.replaceFirst(" ");
}
/* let these end up in extra_remarks
// Significant Cloud Types
// if( s#(CB|CBMAM|TCU|ACC|SCSL|ACSL|ROTOR CLD|ROPE|ROPE CLD)\s+## )
// $Sign_cloud = padstr( $1, 10 ) ;
// $Sign_dist = padstr( $1, 10 )
// if( s#^(VCNTY STN|VCY STN|VC STN|VCY|VC|DSNT|OMT)\s+## ) ;
// $Sign_dir = padstr( "$1$2$3", 10 )
// if( s#^(NE|NW|SE|SW|N|S|E|W)(\-| MOV )?(NE|NW|SE|SW|N|S|E|W)?/?\s+## ) ;
m = MP.significantCloud.matcher(remark);
if (m.find()) {
field.put("Significant_Cloud", m.group(1));
unit.put("Significant_Cloud", "");
remark = m.replaceFirst(" ");
m = MP.significantCloud1.matcher(remark);
if (m.find()) {
field.put("Significant_Cloud_Vicinity", m.group(1));
unit.put("Significant_Cloud_Vicinity", "" );
remark = m.replaceFirst(" ");
m = MP.significantCloud2.matcher(remark);
if (m.find()) {
field.put("Significant_Cloud_Direction", m.group(1));
unit.put("Significant_Cloud_Direction", "");
remark = m.replaceFirst(" ");
}
}
}
*/
/* let these end up in extra_remarks
// Obscuring Phenomena Aloft
// if( s#(VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)? (FEW|SCT|BKN|OVC)(\d3)\s+## )
// $ObscurAloft = padstr( "$1$2$3$4$5", 8 ) ;
// $ObscurAloftSkyCond = $6 ;
// $ObscurAloftHgt = $7 * 100 ;
//
m = MP.obscuringPhen.matcher(remark);
if (m.find()) {
String tmp = "";
if (m.group(1) != null) {
tmp = m.group(1);
}
if (m.group(2) != null) {
tmp = m.group(2);
}
if (m.group(3) != null) {
tmp = m.group(3);
}
if (m.group(4) != null) {
tmp = m.group(4);
}
if (m.group(5) != null) {
tmp = m.group(5);
}
if ( ! tmp.equals("")) {
field.put("Surface_Phenomena", tmp );
unit.put("Surface_Phenomena", "" );
}
field.put("Obscuring_Phenomena_Sky", m.group(6));
unit.put("Obscuring_Phenomena_Sky", "");
if (m.group(7) != null) {
field.put("Obscuring_Phenomena_Sky_Height", Integer.toString(Integer.parseInt(m.group(7)) * 100));
unit.put("Obscuring_Phenomena_Sky_Height", "feet");
}
remark = m.replaceFirst(" ");
}
*/
// Air craft mishap ACFTMSHP
// $ACFTMSHP = 1 if( s#\(?ACFT\s?MSHP\)?\s+## ) ;
m = MP.ACFT.matcher(remark);
if (m.find()) {
field.put("Air_craft_mishap", "yes");
unit.put("Air_craft_mishap", "");
remark = m.replaceFirst(" ");
}
// No changes in weather conditions until next report NOSPECI
// $NOSPECI = 1 if( s#NOSPECI\s+## ) ;
m = MP.NOSPECI.matcher(remark);
if (m.find()) {
field.put("Changes_in_weather", "No");
unit.put("Changes_in_weather", "");
remark = m.replaceFirst(" ");
}
// This is first report of the day FIRST
// $FIRST = 1 if( s#FIRST\s+## ) ;
m = MP.FIRST.matcher(remark);
if (m.find()) {
field.put("First_Report_Today", "yes");
unit.put("First_Report_Today", "");
remark = m.replaceFirst(" ");
}
// This is last report in observation coverage LAST
// $LAST = 1 if( s#LAST\s+## ) ;
m = MP.LAST.matcher(remark);
if (m.find()) {
field.put("Last_Report_Today", "yes");
unit.put("Last_Report_Today", "");
remark = m.replaceFirst(" ");
}
// Cloud Types
// if( s# 8/(\d|/)(\d|/)(\d|/)\s+# # )
// $Cloud_low = $1 ;
// $Cloud_medium = $2 ;
// $Cloud_high = $3 ;
m = MP.cloud_height.matcher(remark);
if (m.find()) {
if( ! m.group(1).equals( "/")) {
field.put("Cloud_Low", m.group(1));
unit.put("Cloud_Low", "");
}
if( ! m.group(2).equals( "/")) {
field.put("Cloud_Medium", m.group(2));
unit.put("Cloud_Medium", "");
}
if( ! m.group(3).equals( "/")) {
field.put("Cloud_High", m.group(3));
unit.put("Cloud_High", "");
}
remark = m.replaceFirst(" ");
}
//
// Snow Increasing Rapidly SNINCR
// if( s#SNINCR (\d1,3)/(\d1,3)\s+## )
// $SNINCR = $1 ;
// $SNINCR_TotalDepth = $2 ;
m = MP.SNINCR.matcher(remark);
if (m.find()) {
field.put("Snow_Increasing_Rapidly", m.group(1));
unit.put("Snow_Increasing_Rapidly", "inches");
field.put("Snow_Increasing_Depth", m.group(2));
unit.put("Snow_Increasing_Depth", "inches");
remark = m.replaceFirst(" ");
}
//
// Snow depth on ground
// if( s#4/(\d1,3)\s+# # )
// $SN_depth = $1 ;
m = MP.snowDepth.matcher(remark);
if (m.find()) {
field.put("Snow_Depth", m.group(1));
unit.put("Snow_Depth", "inches");
remark = m.replaceFirst(" ");
}
//
// Water equivalent of snow on ground
// $SN_waterequiv = $1 / 10 if( s# 933(\d3)\s+# # ) ;
m = MP.waterEquiv.matcher(remark);
if (m.find()) {
field.put("Water_Equivalent_of_Snow", Double.toString(Float.parseFloat(m.group(1)) * 0.1 ));
unit.put("Water_Equivalent_of_Snow", "");
remark = m.replaceFirst(" ");
}
// Duration of sunshine
// if( s# 98(\d1,3|///)\s+# # )
// if( $1 eq "///" )
// $SunSensorOut = 1 ;
// else
// $SunShineDur = $1 ;
m = MP.sunShine.matcher(remark);
if (m.find()) {
if( m.group(1).equals("///") ) {
field.put("Sun_Sensor_working", "No");
unit.put("Sun_Sensor_working", "");
} else {
field.put("Sun_Sensor_Duration", m.group(1));
unit.put("Sun_Sensor_Duration", "");
}
remark = m.replaceFirst(" ");
}
// Precipitation amount
// if( s# 6(\d4|////)\s+# # )
// $PRECIP_amt = $1 / 100 if( $1 ne "////" ) ;
m = MP.precipitation.matcher(remark);
if (m.find()) {
if( ! m.group(1).equals("////") ) {
field.put("Precipitation_amount", Double.toString(Float.parseFloat(m.group(1)) * 0.01 ));
unit.put("Precipitation_amount", "inches");
}
remark = m.replaceFirst(" ");
}
//
// 24 Hour Precipitation amount
// if( s# 7(\d4|////)\s+# # )
// $PRECIP_24_amt = $1 / 100 if( $1 ne "////" ) ;
m = MP.precipitation24.matcher(remark);
if (m.find()) {
if( ! m.group(1).equals("////") ) {
field.put("Precipitation_amount_24Hours", Double.toString(Float.parseFloat(m.group(1)) * 0.01 ));
unit.put("Precipitation_amount_24Hours", "inches");
}
remark = m.replaceFirst(" ");
}
//
// Maximum Temperature
// if( s# 1(0|1|/)(\d3|///)\s+# # )
// $Tmax = $2 / 10 if( $2 ne "///" ) ;
// $Tmax *= -1.0 if( $1 == 1 ) ;
//
m = MP.maxTemperature.matcher(remark);
if (m.find()) {
if( ! m.group(2).equals("///") ) {
double maxtemp = Float.parseFloat(m.group(2));
if( m.group(1).equals("1") ) {
maxtemp *= -0.1;
} else if( m.group(1).equals("0") ) {
maxtemp *= 0.1;
}
field.put("Max_Temperature", Double.toString( maxtemp ) );
unit.put("Max_Temperature", "Celsius");
}
remark = m.replaceFirst(" ");
}
// Minimum Temperature
// if( s# 2(0|1|/)(\d3|///)\s+# # )
// $Tmin = $2 / 10 if( $2 ne "///" ) ;
// $Tmin *= -1.0 if( $1 == 1 ) ;
m = MP.minTemperature.matcher(remark);
if (m.find()) {
if( ! m.group(2).equals("///") ) {
double mintemp = Float.parseFloat(m.group(2));
if( m.group(1).equals("1") ) {
mintemp *= -0.1;
} else if( m.group(1).equals("0") ) {
mintemp *= 0.1;
}
field.put("Min_Temperature", Double.toString( mintemp ) );
unit.put("Min_Temperature", "Celsius");
}
remark = m.replaceFirst(" ");
}
//
// 24-Hour Maximum and Minimum Temperature
// if( s# 4(0|1|/)(\d3|///)(0|1|/)(\d3|///)\s+# # )
// $Tmax24 = $2 / 10 if( $2 ne "///" ) ;
// $Tmax24 *= -1.0 if( $1 == 1 ) ;
// $Tmin24 = $4 / 10 if( $4 ne "///" ) ;
// $Tmin24 *= -1.0 if( $3 == 1 ) ;
m = MP.maxMinTemp24.matcher(remark);
if (m.find()) {
if( ! m.group(2).equals("///") ) {
double maxtemp = Float.parseFloat(m.group(2));
if( m.group(1).equals("1") ) {
maxtemp *= -0.1;
} else if( m.group(1).equals("0") ) {
maxtemp *= 0.1;
}
field.put("Max_Temperature_24Hour", Double.toString( maxtemp ) );
unit.put("Max_Temperature_24Hour", "Celsius");
}
if( ! m.group(4).equals("///") ) {
double mintemp = Float.parseFloat(m.group(4));
if( m.group(3).equals("1") ) {
mintemp *= -0.1;
} else if( m.group(3).equals("0") ) {
mintemp *= 0.1;
}
field.put("Min_Temperature_24Hour", Double.toString( mintemp ) );
unit.put("Min_Temperature_24Hour", "Celsius");
}
remark = m.replaceFirst(" ");
}
//
// Presure Tendency
// if( s# 5(0|1|2|3|4|5|6|7|8)(\d3/?|///)\s+# # )
// $char_Ptend = $1 ;
// $Ptend = $2 / 10 if( $2 ne "///" ) ;
//
m = MP.pressureTendency.matcher(remark);
if (m.find()) {
field.put("Presure_Tendency_char", m.group(1));
unit.put("Presure_Tendency_char", "");
if( ! m.group(2).equals("///") ) {
field.put("Presure_Tendency", Double.toString(Float.parseFloat(m.group(2)) * 0.1 ));
unit.put("Presure_Tendency", "hectopascals");
}
remark = m.replaceFirst(" ");
}
// Freezing Rain sensor not working FZRANO
// $FZRANO = 1 if( s#FZRANO\s+## ) ;
m = MP.FZRANO.matcher(remark);
if (m.find()) {
field.put("Freezing_Rain_sensor_working", "No");
unit.put("Freezing_Rain_sensor_working", "");
remark = m.replaceFirst(" ");
}
// Tipping bucket rain gauge is inoperative.
// $PNO = 1 if( s#PNO\s+## ) ;
m = MP.PNO.matcher(remark);
if (m.find()) {
field.put("Tipping_bucket_rain_gauge_working", "No");
unit.put("Tipping_bucket_rain_gauge_working", "");
remark = m.replaceFirst(" ");
}
// Maintenance is needed on system Indicator
// $maintIndicator = 1 if( s#\$\s+## ) ;
m = MP.maintenace.matcher(remark);
if (m.find()) {
field.put("Maintenance_needed", "yes");
unit.put("Maintenance_needed", "");
remark = m.replaceFirst(" ");
}
/* let this go to the extra fields field cuz it's too general
// Get Recent weather conditions with Beginning and Ending times, moved
// because the RE are too general and they match wrongly
// code table 4678
for(int i = 0; i < 3; i++ ) {
String RWX = "Recent_Weather_"+ Integer.toString( i +1 );
// if( s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?B(\d2,4)E(\d2,4)\s+## )
m = MP.recentWeather.matcher(remark);
if (m.find()) {
// $Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ;
String tmp = "";
if (m.group(1) != null) {
tmp = m.group(1);
}
if (m.group(2) != null) {
tmp = tmp + m.group(2);
}
if (m.group(3) != null) {
tmp = tmp + m.group(3);
}
if (m.group(4) != null) {
tmp = tmp + m.group(4);
}
if (m.group(5) != null) {
tmp = tmp + m.group(5);
}
if ( ! tmp.equals("")) {
field.put( RWX, tmp );
unit.put( RWX, "" );
} else {
break;
}
// if( length( $6 ) == 5 )
// $Recent_WX_Bhh[ $i ] = substr( $6, 1, 2 ) * 1 ;
// $Recent_WX_Bmm[ $i ] = substr( $6, 3, 2 ) * 1 ;
// elsif( length( $6 ) == 3 )
// $Recent_WX_Bmm[ $i ] = substr( $6, 1, 2 ) * 1 ;
field.put( RWX +"_Begin_Time", m.group(6) );
unit.put( RWX +"_Begin_Time", "" );
// if( length( $7 ) == 5 )
// $Recent_WX_Ehh[ $i ] = substr( $7, 1, 2 ) * 1 ;
// $Recent_WX_Emm[ $i ] = substr( $7, 3, 2 ) * 1 ;
// elsif( length( $7 ) == 3 )
// $Recent_WX_Emm[ $i ] = substr( $7, 1, 2 ) * 1 ;
field.put( RWX +"_End_Time", m.group(7) );
unit.put( RWX +"_End_Time", "" );
remark = m.replaceFirst(" ");
// elsif( s#(\+|-|VC|PR)?(MI|BC|DR|BL|SH|TS|FZ)?(DZ|RA|SN|SG|IC|PE|PL|GR|GS|UP)?(BR|FG|FU|VA|DU|SA|HZ|PY)?(PO|SQ|FC|SS|DS)?(B|E)(\d2,4)\s+## )
} else {
m = MP.recentWeather1.matcher(remark);
if (m.find()) {
// $Recent_WX[ $i ] = padstr( "$1$2$3$4$5", 8 ) ;
String tmp = "";
if (m.group(1) != null) {
tmp = m.group(1);
}
if (m.group(2) != null) {
tmp = tmp + m.group(2);
}
if (m.group(3) != null) {
tmp = tmp + m.group(3);
}
if (m.group(4) != null) {
tmp = tmp + m.group(4);
}
if (m.group(5) != null) {
tmp = tmp + m.group(5);
}
if ( ! tmp.equals("")) {
field.put( RWX, tmp );
unit.put( RWX, "" );
} else {
break;
}
// if( $6 eq "B" && ( length( $7 ) == 4 ))
// $Recent_WX_Bhh[ $i ] = substr( $7, 0, 2 ) * 1 ;
// $Recent_WX_Bmm[ $i ] = substr( $7, 2, 2 ) * 1 ;
// elsif( $6 eq "B" && ( length( $7 ) == 2 ))
// $Recent_WX_Bmm[ $i ] = substr( $7, 0, 2 ) * 1 ;
if( m.group(6).equals("B" ) ) {
field.put( RWX +"_Begin_Time", m.group(7) );
unit.put( RWX +"_Begin_Time", "" );
// elsif( $6 eq "E" && ( length( $7 ) == 4 ))
// $Recent_WX_Ehh[ $i ] = substr( $7, 0, 2 ) * 1 ;
// $Recent_WX_Emm[ $i ] = substr( $7, 2, 2 ) * 1 ;
// elsif( $6 eq "E" && ( length( $7 ) == 2 ))
// $Recent_WX_Emm[ $i ] = substr( $7, 0, 2 ) * 1 ;
} else {
field.put( RWX +"_End_Time", m.group(7) );
unit.put( RWX +"_End_Time", "" );
}
remark = m.replaceFirst(" ");
} else {
// last ;
break;
}
}
} // end for recent weather
*/
// Extra remarks includes Volcanic eruptions
m = MP.spaces.matcher(remark);
if (m.find()) {
remark = m.replaceFirst("");
}
if( remark.length() != 0) {
field.put("Extra_fields", remark );
unit.put("Extra_fields", "");
}
return true;
} // end parseReport
// convert cloud height to meters
private String cloud_hgt2_meters(String height) {
if (height.equals("999")) {
return "30000";
} else {
// $meters = 30 * $height ;
return Integer.toString(30 * Integer.parseInt(height));
}
} // end cloud_hgt2_meters
/**
* Used to return fields in Metar report.
* @return LinkedHashMap
**/
public LinkedHashMap getFields() {
return field;
}
/**
* Used to return units of the fields in Metar report.
* @return LinkedHashMap
**/
public HashMap getUnits() {
return unit;
}
public static void main(String args[]) throws IOException {
String report = null;
//report = "KD07 150256Z AUTO 28005KT BR M08/M11 A3005 RMK AO2 SLP223 T10781111 21205 40051//// 50006 PWINO FZRANO";
//report = "METAR K1V4 251254Z AUTO 01/01 A3002 RMK AO2 SLP172 P0001 T00110006 PWINO FZRANO TSNO ";
//report = "KDEN 201453Z 35007KT 1/4SM R35L/5000V6000FT -DZ BR -SG -FZDZ OVC003 05/04 A2996 RMK 70155 53777 61111 8/53/";
//report = "ROBB 201453Z 35007KT 1/4SM RMK AO1 21200 4/12 T00110006 SLPNO SLP067 P0000";
//report = "ROBB 201453Z NVRB05G15KT 090V180 1/4SM AUTO RMK PWINO TSNO TORNADO B10 DSNT NE";
//report = "ROBB 201453Z NVRB05G15KT R26/0450V0650D RMK PWINO TSNO TORNADO B10 DSNT NE";
//report = "ROBB 201453Z SKC VV312 RMK TORNADO B10 DSNT NE";
//report = "KDEN 201453Z 35007KT 1/4SM R35L/5000V6000FT -DZ BR -SG -FZDZ OVC003 05/04 A2996 RMK CIG 003V006";
//report = "KDEN 201553Z 01006KT 1/4SM R35L/4500VP6000FT -DZ BR OVC003 05/04 A2996 RMK AO2 SFC VIS 3/4 CIG 003V006 SLP124 P0000 T00500044";
//report = "SOCA 202000Z 10003KT 9999 VCSH FEW010CB SCT015TCU 27/26 Q1010 NOSIG TEMPO 4000 CB & TCU AU S ET W";
//report = "SOCA 202000Z 10003KT RMK LTG DSNT SE VIS 6 5/10 RY11 WSHFT 1853 FROPA SLP575 TEMPO 4000 CB & TCU AU S ET W";
report = "SOCA 202000Z 10003KT RMK 98015 933002" +
" CIGNO CIG 125 OVC V BKN -FZRA $";
// Function References
MetarParseReport func = new MetarParseReport();
if( args.length == 1 ) { // read external file of Metar reports
System.out.println( args[ 0 ] +" "+ args.length );
// read reports from file to parse
InputStream ios = new FileInputStream( args[ 0 ] );
BufferedReader dataIS =
new BufferedReader(new InputStreamReader(ios));
//System.out.println("<report>");
while (true) {
report = dataIS.readLine();
if (report == null) {
break;
}
System.out.println( "\n"+ report );
if( ! func.parseReport(report) ) {
System.out.println("badly formed report, can't parse");
continue; // bad report, can't parse
}
LinkedHashMap field = func.getFields();
HashMap unit = func.getUnits();
String key;
System.out.println("<report>");
for( Iterator it = field.keySet().iterator(); it.hasNext(); ) {
key = (String) it.next();
//System.out.println(key + "\t\t" + (String) field.get(key));
System.out.println("\t<parameter name=\""+ key +"\" value=\""+
(String) field.get(key) +"\" units=\""+ (String) unit.get(key)
+"\" />" );
}
System.out.println("</report>");
}
//System.out.println("</report>");
return;
}
// else
System.out.println( report );
if( ! func.parseReport(report) ) {
System.out.println("badly formed report, can't parse");
System.exit(1);
}
LinkedHashMap field = func.getFields();
HashMap unit = func.getUnits();
String key;
System.out.println("<report>");
for( Iterator it = field.keySet().iterator(); it.hasNext(); ) {
key = (String) it.next();
//System.out.println(key + "\t\t" + (String) field.get(key));
System.out.println("\t<parameter name=\""+ key +"\" value=\""+
(String) field.get(key) +"\" units=\""+ (String) unit.get(key)
+"\" />" );
}
System.out.println("</report>");
}
} // end MetarParseReport