CVS: phpweather data_retrieval.php,1.32,1.33 phpweather.php,1.34,1.35...
Brought to you by:
iridium
|
From: Etienne T. <eti...@us...> - 2003-09-13 02:38:55
|
Update of /cvsroot/phpweather/phpweather
In directory sc8-pr-cvs1:/tmp/cvs-serv17699
Modified Files:
data_retrieval.php phpweather.php test2.php
Log Message:
Added hour-by-hour decoding of the taf. test2.php was modified to show that. Interpolation is done in BECMG periods and PROB periods are not added to the hour-by-hour report.
Index: data_retrieval.php
===================================================================
RCS file: /cvsroot/phpweather/phpweather/data_retrieval.php,v
retrieving revision 1.32
retrieving revision 1.33
diff -u -3 -r1.32 -r1.33
Index: phpweather.php
===================================================================
RCS file: /cvsroot/phpweather/phpweather/phpweather.php,v
retrieving revision 1.34
retrieving revision 1.35
diff -u -3 -r1.34 -r1.35
--- phpweather.php 8 Sep 2003 04:20:44 -0000 1.34
+++ phpweather.php 13 Sep 2003 02:38:49 -0000 1.35
@@ -288,7 +288,7 @@
$group['ft'] = round($regs[1] * 3.28084);
}
if (!empty($regs[2])) {
- $group['dir'] = $regs[2];
+ $group['deg'] = $regs[2];
}
$decoded_metar['visibility'][] = $group;
@@ -701,6 +701,12 @@
* @see $decoded_taf
* @access public
*/
+
+ //from http://www.nws.noaa.gov/mdl/icwf/avnfps/editor.html#TAFDecoder
+ //need to add NIL( AMD) (augmented data)
+ //and time consistency checks, Consistency Checks Within a Group
+
+
function decode_taf() {
/* initialization */
@@ -759,6 +765,7 @@
/* for each period, parse the data */
if(count($periods)>0) {
+ $last_fm_becmg = false;
for($j=0;$j<count($periods);$j++) {
$tmp_period = $periods[$j];
$data_period = $tmp_period;
@@ -774,22 +781,38 @@
if ( (substr($parts[0],0,2)=='FM') ) {
$type = 'FM';
$time_from = substr($parts[0],2,4);
- $time_to = false;
+ $time_set = $time_from;
+ $time_to = false;
$first_i = 1;
+ /* set the end time if the previous FM or BECMG to the start time of this one */
+ if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) {
+ $decoded_periods[$last_fm_becmg]['time_to'] = $time_from;
+ }
+ $last_fm_becmg = $j;
}
else if ($parts[0]=='BECMG') {
$type = 'BECMG';
+ $time_from = substr($parts[1],0,2).'00';
+ $time_set = substr($parts[1],2,2).'00';
+ $time_to = false;
$first_i = 2;
+ /* set the end time if the previous FM or BECMG to the start time of this one */
+ if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) {
+ $decoded_periods[$last_fm_becmg]['time_to'] = $time_from;
+ }
+ $last_fm_becmg = $j;
}
else if ($parts[0]=='TEMPO') {
$type = 'TEMPO';
$time_from = substr($parts[1],0,2).'00';
+ $time_set = $time_from; //could interpolate for the first half ?
$time_to = substr($parts[1],2,2).'00';
$first_i = 2;
}
else if (substr($parts[0],0,4)=='PROB') {
$type = 'PROB';
$time_from = substr($parts[1],0,2).'00';
+ $time_set = $time_from;
$time_to = substr($parts[1],2,2).'00';
$prob = intval(substr($parts[0],4));
$first_i = 2;
@@ -798,6 +821,7 @@
$type = 'COMPLETE';
$data_period = substr($data_period,9);
$time_from = substr($parts[1],2,2).'00';
+ $time_set = $time_from;
$time_to = substr($parts[1],4,2).'00';
$first_i = 2;
}
@@ -809,6 +833,7 @@
$decoded_period['type'] = $type;
$decoded_period['time_from'] = $time_from;
$decoded_period['time_to'] = $time_to;
+ $decoded_period['time_set'] = $time_set;
$decoded_period['prob'] = $prob;
/* pass each element of the period */
@@ -818,12 +843,12 @@
if (ereg('^([0-9]{3}|VRB)([0-9]{2,3})G?([0-9]{2,3})?(KT)', $part, $regs)) {
/* Wind Group */
- $decoded_period['wind']['deg'] = $regs[1];
+ $decoded_period['desc']['wind']['deg'] = $regs[1];
$this->store_speed($regs[2],
$regs[4],
- $decoded_period['wind']['knots'],
- $decoded_period['wind']['meters_per_second'],
- $decoded_period['wind']['miles_per_hour']);
+ $decoded_period['desc']['wind']['knots'],
+ $decoded_period['desc']['wind']['meters_per_second'],
+ $decoded_period['desc']['wind']['miles_per_hour']);
if (!empty($regs[3])) {
@@ -832,17 +857,17 @@
*/
$this->store_speed($regs[3],
$regs[4],
- $decoded_period['wind']['gust_knots'],
- $decoded_period['wind']['gust_meters_per_second'],
- $decoded_period['wind']['gust_miles_per_hour']);
+ $decoded_period['desc']['wind']['gust_knots'],
+ $decoded_period['desc']['wind']['gust_meters_per_second'],
+ $decoded_period['desc']['wind']['gust_miles_per_hour']);
}
} elseif (ereg('^([0-9]{3})V([0-9]{3})$', $part, $regs) &&
- !empty($decoded_period['wind']['deg'])) {
+ !empty($decoded_period['desc']['wind']['deg'])) {
/*
* Variable wind-direction
*/
- $decoded_period['wind']['var_beg'] = $regs[1];
- $decoded_period['wind']['var_end'] = $regs[2];
+ $decoded_period['desc']['wind']['var_beg'] = $regs[1];
+ $decoded_period['desc']['wind']['var_end'] = $regs[2];
} elseif (ereg('^([0-9]{4})([NS]?[EW]?)$', $part, $regs)) {
/*
* Visibility in meters (4 digits only)
@@ -873,9 +898,9 @@
$group['ft'] = round($regs[1] * 3.28084);
}
if (!empty($regs[2])) {
- $group['dir'] = $regs[2];
+ $group['deg'] = $regs[2];
}
- $decoded_period['visibility'][] = $group;
+ $decoded_period['desc']['visibility'][] = $group;
} elseif (ereg('^[0-9]$', $part)) {
/*
@@ -887,11 +912,11 @@
unset($group);
$group['prefix'] = 1;
$vis_miles = 6;
- $group['miles'] = number_format($vis_miles, 1);
+ $group['miles'] = $vis_miles;
$group['ft'] = round($vis_miles * 5280, 1);
$group['km'] = number_format($vis_miles * 1.6093, 1);
$group['meter'] = round($vis_miles * 1609.3);
- $decoded_period['visibility'][] = $group;
+ $decoded_period['desc']['visibility'][] = $group;
} elseif (ereg('^[M]?(([0-9]?)[ ]?([0-9])(/?)([0-9]*))SM$',
$temp_visibility_miles . ' ' . $part, $regs)) {
@@ -924,11 +949,11 @@
/* The visibility measured in meters */
$group['meter'] = round($vis_miles * 1609.3);
- $decoded_period['visibility'][] = $group;
+ $decoded_period['desc']['visibility'][] = $group;
} elseif (ereg('^(VC)?' . /* Proximity */
'(-|\+)?' . /* Intensity */
- '(MI|PR|BC|DR|BL|SH|TS|FZ)?' . /* Descriptor */
+ '(MI|PR|BC|DR|BL|SH|TS|FZ|NSW)?' . /* Descriptor */
'((DZ|RA|SN|SG|IC|PL|GR|GS|UP)+)?' . /* Precipitation */
'(BR|FG|FU|VA|DU|SA|HZ|PY)?' . /* Obscuration */
'(PO|SQ|FC|SS)?$', /* Other */
@@ -936,7 +961,7 @@
/*
* Current weather-group.
*/
- $decoded_period['weather'][] =
+ $decoded_period['desc']['weather'][] =
array('proximity' => $regs[1],
'intensity' => $regs[2],
'descriptor' => $regs[3],
@@ -946,7 +971,7 @@
} elseif ($part == 'SKC' || $part == 'CLR') {
/* Cloud-group */
- $decoded_period['clouds'][]['condition'] = $part;
+ $decoded_period['desc']['clouds'][]['condition'] = $part;
} elseif (ereg('^(VV|FEW|SCT|BKN|OVC)([0-9]{3}|///)' .
'(CB|TCU)?$', $part, $regs)) {
@@ -970,7 +995,7 @@
$group['ft'] = $regs[2] *100;
$group['meter'] = round($regs[2] * 30.48);
}
- $decoded_period['clouds'][] = $group;
+ $decoded_period['desc']['clouds'][] = $group;
} elseif (ereg('^WS([0-9]{3})/([0-9]{3})([0-9]{2})KT$', $part, $regs)) {
/* We have found a Wind Shear group. example WS011/27050KT */
@@ -987,18 +1012,90 @@
$ws['ft'] = $regs[1] *100;
$ws['meter'] = round($regs[1] * 30.48);
}
- $ws['wind']['dir'] = $regs[2];
+ $ws['wind']['deg'] = $regs[2];
$this->store_speed($regs[3],'KT',
$ws['wind']['knots'],
$ws['wind']['meters_per_second'],
$ws['wind']['miles_per_hour']);
- $decoded_period['wind_shear'][] = $ws;
+ $decoded_period['desc']['wind_shear'][] = $ws;
}
}
}
- $decoded_taf['periods'] = $decoded_periods;
+
+ /* set the last FM or BECMG end time */
+ if($last_fm_becmg!==false && $decoded_periods[$last_fm_becmg]['time_to']===false) {
+ $decoded_periods[$last_fm_becmg]['time_to'] = $decoded_periods[0]['time_to'];
+ }
+
+ $decoded_taf['periods1'] = $decoded_periods;
$decoded_taf['remarks'] = trim($decoded_taf['remarks']);
}
+
+ //ET tmp pass each period and fill in the missing pieces
+ /*
+ * taken from http://www.srh.noaa.gov/ftproot/MSD/html/note7.html
+ * includes icing, turbulence and temp forecast
+ *
+ * FM change rapidly within less than one hour ->from begin to end
+ * BECMG change slowly, normally within 2 hours, never exceed 4 hours -> interpolate each 30 min
+ * TEMPO temporary, less than half of the period ->from 1/4 to 3/4 interpolating
+ * PROB chance of occurence for the whole period ->from begin to end
+ */
+
+ $decoded_periods2 = array();
+ $full_period = $full_period2 = false;
+
+ /* for each period, parse the data */
+ if(count($decoded_taf['periods1'])>0) {
+ $full_period = $decoded_taf['periods1'][0];
+ for($j=0;$j<count($decoded_taf['periods1']);$j++) {
+ $tmp_period = $decoded_taf['periods1'][$j];
+ $tmp_period2 = false;
+
+ /* merge the permanent period with this one */
+ if($tmp_period['type'] == "COMPLETE") $tmp_period2 = $full_period;
+ else $tmp_period2 = $this->merge_period($tmp_period,$full_period);
+
+ /* fill $decoded_periods3 with data from each hour */
+ $time_from = $tmp_period2['time_from'];
+ $tms_from = gmmktime(substr($time_from,0,2),(substr($time_from,2,2)));
+ $time_set = $tmp_period2['time_set'];
+ $tms_set = gmmktime(substr($time_set,0,2),(substr($time_set,2,2)));
+ $time_to = $tmp_period2['time_to'];
+ $tms_to = gmmktime(substr($time_to,0,2),(substr($time_to,2,2)));
+ if($time_to <= $time_from ) $tms_to += 24*60*60;
+ if($time_set < $time_from ) $tms_set += 24*60*60;
+ $duration = ($tms_to - $tms_from) / 60.0 / 60.0;
+ for($k=0;$k<ceil($duration);$k++) {
+ $tmp_period3 = $tmp_period2;
+ $tmp_tms_from = $tms_from + $k * 60*60;
+ $tmp_tms_to = $tmp_tms_from + 60*60;//see if fraction...
+ $tmp_time_from = gmdate("Hi",$tmp_tms_from);
+ $tmp_time_to = gmdate("Hi",$tmp_tms_to);
+ $tmp_period3['time_from'] = $tmp_time_from;
+ $tmp_period3['time_to'] = $tmp_time_to;
+ unset($tmp_period3['time_set']);
+ if($tmp_tms_from < $tms_set) {
+ $tmp_period3['interpolate']='yes';
+ $this->interpolate_period($tmp_period3,$full_period2,$tms_from,$tms_set,$tmp_tms_from,$tmp_tms_to);
+ }
+ /* for now do not include PROB in the hour-by-hour */
+ if ($tmp_period['type'] != "PROB") {
+ $decoded_periods3[gmdate("H",$tmp_tms_from)] = $tmp_period3;
+ }
+ }
+
+ /* apply the permanent change for the next periods */
+ if($tmp_period['type'] != "TEMPO" && $tmp_period['type'] != "PROB") {
+ $full_period2 = $full_period;
+ $full_period = $tmp_period2;
+ }
+ $decoded_periods2[$j] = $tmp_period2;
+ }
+ $decoded_taf['periods2'] = $decoded_periods2;
+ $decoded_taf['periods3'] = $decoded_periods3;
+ }
+
/* Finally we store our decoded TAF in $this->decoded_taf so
* that other methods can use it.
@@ -1007,6 +1104,60 @@
$this->decoded_taf = $decoded_taf;
return $decoded_taf;
+ }
+
+ function merge_period(&$period1,&$period2) {
+ $period = $period2;
+ reset($period1);
+ while(list($key,$val) = each($period1)) {
+ if(is_array($val)) {
+ while(list($key2,$val2) = each($val)) {
+ $period[$key][$key2] = $val2;
+ }
+ }
+ else
+ $period[$key] = $val;
+ }
+ return $period;
+ }
+
+ function add_time($str_time,$add_hour,$add_min=0) {
+ $tms = gmmktime(substr($str_time,0,2),(substr($str_time,2,2)));
+ $tms += $add_hour*60*60 + $add_min*60;
+ return gmdate("Hi",$tms);
+ }
+
+
+ function interpolate_period(&$period,&$prev_period,$from,$set,$period_from,$period_to) {
+ //only interpolate wind, not: -visibility -weather -clouds -ws
+ $wind = $period['desc']['wind'];
+ $prev_wind = $prev_period['desc']['wind'];
+ $factor = ($period_to-$from)/($set-$from+60*60);
+
+ $tmp_wind_speed1 = intval($prev_wind['knots']);
+ $tmp_wind_speed2 = intval($wind['knots']);
+ $tmp_wind_speed = $tmp_wind_speed1 + $factor*($tmp_wind_speed2-$tmp_wind_speed1);
+
+ /* if VRB special treatment : set to VRB when on the VRB half */
+ $tmp_wind_dir1 = $prev_wind['deg'];
+ $tmp_wind_dir2 = $wind['deg'];
+ if ($tmp_wind_speed1==0) $tmp_wind_dir = $tmp_wind_dir2;
+ else if ($tmp_wind_speed2==0) $tmp_wind_dir = $tmp_wind_dir1;
+ else {
+ if( ($tmp_wind_dir1=='VRB' && $tmp_wind_dir1=='VRB') ||
+ ($factor<0.5 && $tmp_wind_dir1=='VRB') ||
+ ($factor>0.5 && $tmp_wind_dir2=='VRB') ) {
+ $tmp_wind_dir = 'VRB';
+ }
+ else
+ $tmp_wind_dir = $tmp_wind_dir1 + $factor*($tmp_wind_dir2-$tmp_wind_dir1);
+ }
+
+ /* set the average values */
+ $period['desc']['wind']['deg'] = $tmp_wind_dir;
+ $this->store_speed($tmp_wind_speed,'KT',$period['desc']['wind']['knots'],
+ $period['desc']['wind']['meters_per_second'],
+ $period['desc']['wind']['miles_per_hour']);
}
}
Index: test2.php
===================================================================
RCS file: /cvsroot/phpweather/phpweather/test2.php,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -3 -r1.1 -r1.2
--- test2.php 8 Sep 2003 04:25:54 -0000 1.1
+++ test2.php 13 Sep 2003 02:38:49 -0000 1.2
@@ -15,6 +15,7 @@
if (empty($language)) $language = 'en';
$weather = new phpweather();
+// $weather->properties['verbosity'] = 5;
if (!empty($icao)) {
@@ -46,12 +47,25 @@
$weather->set_icao($icao);
+ $language = 'en';
+ require(PHPWEATHER_BASE_DIR . "/output/pw_text_$language.php");
+ $type = 'pw_text_' . $language;
+ $text = new $type($weather);
+
+ require(PHPWEATHER_BASE_DIR . "/output/pw_images.php");
+ $icons = new pw_images($weather);
+
+ /*
echo "METAR for $icao : ".$weather->get_metar()."<br>\n";
echo "<br>Decoded METAR:<pre>";
print_r( $weather->decode_metar() );
echo "</pre><br>\n";
+ */
echo "TAF for $icao : ".$weather->get_taf()."<br>\n";
+ echo "<br>Print TAF:<br><br>";
+ print_r( $text->print_taf() );
+ echo "<br>\n";
echo "<br>Decoded TAF:<pre>";
print_r( $weather->decode_taf() );
echo "</pre><br>\n";
|