Completed
Push — master ( 34c6fd...b81903 )
by Yannick
06:41
created

METAR::addMETARCycle()   C

Complexity

Conditions 16
Paths 24

Size

Total Lines 37
Code Lines 27

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
eloc 27
nc 24
nop 0
dl 0
loc 37
rs 5.0151
c 0
b 0
f 0

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
require_once(dirname(__FILE__).'/settings.php');
3
require_once(dirname(__FILE__).'/class.Connection.php');
4
require_once(dirname(__FILE__).'/class.Common.php');
5
6
class METAR {
7
	public $db;
8
	
9
	protected $texts = Array(
10
	    'MI' => 'Shallow',
11
	    'PR' => 'Partial',
12
	    'BC' => 'Low drifting',
13
	    'BL' => 'Blowing',
14
	    'SH' => 'Showers',
15
	    'TS' => 'Thunderstorm',
16
	    'FZ' => 'Freezing',
17
	    'DZ' => 'Drizzle',
18
	    'RA' => 'Rain',
19
	    'SN' => 'Snow',
20
	    'SG' => 'Snow Grains',
21
	    'IC' => 'Ice crystals',
22
	    'PL' => 'Ice pellets',
23
	    'GR' => 'Hail',
24
	    'GS' => 'Small hail',
25
	    'UP' => 'Unknown',
26
	    'BR' => 'Mist',
27
	    'FG' => 'Fog',
28
	    'FU' => 'Smoke',
29
	    'VA' => 'Volcanic ash',
30
	    'DU' => 'Widespread dust',
31
	    'SA' => 'Sand',
32
	    'HZ' => 'Haze',
33
	    'PY' => 'Spray',
34
	    'PO' => 'Well developed dust / sand whirls',
35
	    'SQ' => 'Squalls',
36
	    'FC' => 'Funnel clouds inc tornadoes or waterspouts',
37
	    'SS' => 'Sandstorm',
38
	    'DS' => 'Duststorm'
39
	);
40
	
41
	public function __construct($dbc = null) {
42
                $Connection = new Connection($dbc);
43
                $this->db = $Connection->db;
44
        }
45
46
       public static function check_last_update() {
47
    		global $globalDBdriver;
48
    		if ($globalDBdriver == 'mysql') {
49
			$query = "SELECT COUNT(*) as nb FROM config WHERE name = 'last_update_metar' AND value > DATE_SUB(NOW(), INTERVAL 20 MINUTE)";
50
		} else {
51
			$query = "SELECT COUNT(*) as nb FROM config WHERE name = 'last_update_metar' AND value::timestamp > CURRENT_TIMESTAMP - INTERVAL '20 MINUTES'";
52
		}
53
                try {
54
                        $Connection = new Connection();
55
                        $sth = $Connection->db->prepare($query);
56
                        $sth->execute();
57
                } catch(PDOException $e) {
58
                        return "error : ".$e->getMessage();
59
                }
60
                $row = $sth->fetch(PDO::FETCH_ASSOC);
61
                $sth->closeCursor();
62
                if ($row['nb'] > 0) return false;
63
                else return true;
64
        }
65
66
        public static function insert_last_update() {
67
                $query = "DELETE FROM config WHERE name = 'last_update_metar';
68
                        INSERT INTO config (name,value) VALUES ('last_update_metar',NOW());";
69
                try {
70
                        $Connection = new Connection();
71
                        $sth = $Connection->db->prepare($query);
72
                        $sth->execute();
73
                } catch(PDOException $e) {
74
                        return "error : ".$e->getMessage();
75
                }
76
        }
77
78
79
        
80
        public function parse($data) {
81
    		//$data = str_replace(array('\n','\r','\r','\n'),'',$data);
82
    		$codes = implode('|', array_keys($this->texts));
83
    		$regWeather = '#^(\+|\-|VC)?(' . $codes . ')(' . $codes . ')?$#';
84
    		//$pieces = explode(' ',$data);
85
    		$pieces = preg_split('/\s/',$data);
86
    		$pos = 0;
87
    		if ($pieces[0] == 'METAR') $pos++;
88
    		elseif ($pieces[0] == 'SPECI') $pos++;
89
    		if (strlen($pieces[$pos]) != 4) $pos++;
90
    		$result = array();
91
    		$result['location'] = $pieces[$pos];
92
    		$pos++;
93
    		$result['dayofmonth'] = substr($pieces[$pos],0,2);
94
    		$result['time'] = substr($pieces[$pos],2,4);
95
    		$c = count($pieces);
96
    		for($pos++; $pos < $c; $pos++) {
97
    			$piece = $pieces[$pos];
98
    			if ($piece == 'RMK') break;
99
    			if ($piece == 'AUTO') $result['auto'] = true;
100
    			if ($piece == 'COR') $result['correction'] = true;
101
    			// Wind Speed
102
    			if (preg_match('#(VRB|\d\d\d)(\d\d)(?:G(\d\d))?(KT|MPS|KPH)(?: (\d{1,3})V(\d{1,3}))?$#', $piece, $matches)) {
103
    				$result['wind']['direction'] = (float)$matches[1];
104
				$result['wind']['unit'] = $matches[4];
105
    				if ($result['wind']['unit'] == 'KT') $result['wind']['speed'] = round(((float)$matches[2])*0.51444444444,2);
106
    				elseif ($result['wind']['unit'] == 'KPH') $result['wind']['speed'] = round(((float)$matches[2])*1000,2);
107
    				elseif ($result['wind']['unit'] == 'MPS') $result['wind']['speed'] = round(((float)$matches[2]),2);
108
				$result['wind']['gust'] = (float)$matches[3];
109
				$result['wind']['unit'] = $matches[4];
110
				$result['wind']['min_variation'] = array_key_exists(5,$matches) ? $matches[5] : 0;
111
				$result['wind']['max_variation'] = array_key_exists(6,$matches) ? $matches[6] : 0;
112
    			}
113
114
/*    			if (preg_match('#^([0-9]{3})([0-9]{2})(G([0-9]{2}))?(KT|MPS)$#', $piece, $matches)) {
115
    				$result['wind_direction'] = (float)$matches[1];
116
    				if ($matches[5] == 'KT') {
117
    					$result['speed'] = round(((float)$matches[2])*0.51444444444,2);
118
    				} elseif ($matches[5] == 'KPH') {
119
    					$result['speed'] = round(((float)$matches[2])*1000,2);
120
    				} elseif ($matches[5] == 'MPS') {
121
    					$result['speed'] = round(((float)$matches[2]),2);
122
    				}
123
    				if ($matches[3]) {
124
    				    $result['gust'] = $matches[4];
125
    				    $result['gust_format'] = $matches[5];
126
    				}
127
    			}
128
    			*/
129
    			// Temperature
130
    			if (preg_match('#^(M?[0-9]{2,})/(M?[0-9]{2,})$#', $piece, $matches)) {
131
    				$temp = (float)$matches[1];
132
				if ($matches[1]{0} == 'M') {
133
					$temp = ((float)substr($matches[1], 1)) * -1;
134
				}
135
    				$result['temperature'] = $temp;
136
    				$dew = (float)$matches[2];
137
				if ($matches[2]{0} == 'M') {
138
					$dew = ((float)substr($matches[2], 1)) * -1;
139
				}
140
				$result['dew'] = $dew;
141
    			}
142
    			// QNH
143
    			if (preg_match('#^(A|Q)([0-9]{4})$#', $piece, $matches)) {
144
    			// #^(Q|A)(////|[0-9]{4})( )#
145
    				if ($matches[1] == 'Q') {
146
    					// hPa
147
    					$result['QNH'] = $matches[2];
148
    				} else {
149
    					// inHg
150
    					$result['QNH'] = round(($matches[2] / 100)*33.86389,2);
151
				}
152
    				/*
153
    				$result['QNH'] = $matches[1] == 'Q' ? $matches[2] : ($matches[2] / 100);
154
    				$result['QNH_format'] = $matches[1] == 'Q' ? 'hPa' : 'inHg';
155
    				*/
156
    			}
157
                     /*
158
    			// Wind Direction
159
    			if (preg_match('#^([0-9]{3})V([0-9]{3})$#', $piece, $matches)) {
160
    				$result['wind_direction'] = $matches[1];
161
    				$result['wind_direction_other'] = $matches[2];
162
    			}
163
    			// Wind Speed Variable
164
    			if (preg_match('#^VRB([0-9]{2})KT$#', $piece, $matches)) {
165
    				$result['speed_variable'] = $matches[1];
166
    			}
167
    			*/
168
    			// Visibility
169
    			if (preg_match('#^([0-9]{4})|(([0-9]{1,4})SM)$#', $piece, $matches)) {
170
    				if (isset($matches[3]) && strlen($matches[3]) > 0) {
171
					$result['visibility'] = (float)$matches[3] * 1609.34;
172
				} else {
173
					if ($matches[1] == '9999') {
174
						$result['visibility'] = '> 10000';
175
					} else {
176
						$result['visibility'] = (float)$matches[1];
177
					}
178
				}
179
				if (preg_match('#^CAVOK$#', $piece, $matches)) {
180
					$result['visibility'] = '> 10000';
181
					$result['weather'] = "CAVOK";
182
				}
183
    			}
184
    			// Cloud Coverage
185
    			if (preg_match('#^(SKC|CLR|FEW|SCT|BKN|OVC|VV)([0-9]{3})(CB|TCU|CU|CI)?$#', $piece, $matches)) {
186
    				//$this->addCloudCover($matches[1], ((float)$matches[2]) * 100, isset($matches[3]) ? $matches[3] : '');
187
    				$type = $matches[1];
188
    				$cloud = array();
189
    				if ($type == 'SKC') $cloud['type'] = 'No cloud/Sky clear';
190
    				elseif ($type == 'CLR') $cloud['type'] = 'No cloud below 12,000ft (3700m)';
191
    				elseif ($type == 'NSC') $cloud['type'] = 'No significant cloud';
192
    				elseif ($type == 'FEW') $cloud['type'] = 'Few';
193
    				elseif ($type == 'SCT') $cloud['type'] = 'Scattered';
194
    				elseif ($type == 'BKN') $cloud['type'] = 'Broken';
195
    				elseif ($type == 'OVC') $cloud['type'] = 'Overcast/Full cloud coverage';
196
    				elseif ($type == 'VV') $cloud['type'] = 'Vertical visibility';
197
    				$cloud['type_code'] = $type;
198
    				$cloud['level'] = round(((float)$matches[2]) * 100 * 0.3048);
199
    				$cloud['significant'] = isset($matches[3]) ? $matches[3] : '';
200
    				$result['cloud'][] = $cloud;
201
    			}
202
    			// RVR
203
    			 if (preg_match('#^(R.+)/([M|P])?(\d{4})(?:V(\d+)|[UDN])?(FT)?$#', $piece, $matches)) {
204
    				$rvr = array();
205
				$rvr['runway'] = $matches[1];
206
				$rvr['assessment'] = $matches[2];
207
				$rvr['rvr'] = $matches[3];
208
				$rvr['rvr_max'] = array_key_exists(4,$matches) ? $matches[4] : 0;
209
				$rvr['unit'] = array_key_exists(5,$matches) ? $matches[5] : '';
210
				$result['RVR'] = $rvr;
211
			}
212
    			
213
    			//if (preg_match('#^(R[A-Z0-9]{2,3})/([0-9]{4})(V([0-9]{4}))?(FT)?$#', $piece, $matches)) {
214
    			if (preg_match('#^R(\d{2}[LRC]?)/([\d/])([\d/])([\d/]{2})([\d/]{2})$#', $piece, $matches)) {
215
    				//print_r($matches);
216
    				// https://github.com/davidmegginson/metar-taf/blob/master/Metar.php
217
    				$result['RVR']['runway'] = $matches[1];
218
        			$result['RVR']['deposits'] = $matches[2];
219
        			$result['RVR']['extent'] = $matches[3];
220
        			$result['RVR']['depth'] = $matches[4];
221
        			$result['RVR']['friction'] = $matches[5];
222
    			}
223
    			if (preg_match('#^(R[A-Z0-9]{2,3})/([0-9]{4})(V([0-9]{4}))?(FT)?$#', $piece, $matches)) {
224
    				//echo $piece;
225
    				//print_r($matches);
226
    				if (isset($matches[5])) $range = array('exact' => (float)$matches[2], 'unit' => $matches[5] ? 'FT' : 'M');
227
    				else $range = array('exact' => (float)$matches[2], 'unit' => 'M');
228
				if (isset($matches[3])) {
229
					$range = Array(
230
					    'from' => (float)$matches[2],
231
					    'to'   => (float)$matches[4],
232
					    'unit' => $matches[5] ? 'FT' : 'M'
233
					);
234
				}
235
				$result['RVR'] = $matches[1];
236
				$result['RVR_range'] = $range;
237
    			}
238
    			// Weather
239
    			if (preg_match($regWeather, $piece, $matches)) {
240
				$text = Array();
241
				switch ($matches[1]) {
242
					case '+':
243
						$text[] = 'Heavy';
244
						break;
245
					case '-':
246
						$text[] = 'Light';
247
						break;
248
					case 'VC':
249
						$text[] = 'Vicinity';
250
						break;
251
					default:
252
						break;
253
				}
254
				if (isset($matches[2])) {
255
					$text[] = $this->texts[$matches[2]];
256
				}
257
				if (isset($matches[3])) {
258
					$text[] = $this->texts[$matches[3]];
259
				}
260
				if (!isset($result['weather'])) $result['weather'] = implode(' ', $text);
261
				else $result['weather'] = $result['weather'].' / '.implode(' ', $text);
262
    			}
263
    		}
264
    		return $result;
265
        
266
        }
267
        
268
	public function getMETAR($icao) {
269
    		global $globalMETARcycle, $globalDBdriver;
270
    		if (isset($globalMETARcycle) && $globalMETARcycle) {
271
            		$query = "SELECT * FROM metar WHERE metar_location = :icao";
272
                } else {
273
            		if ($globalDBdriver == 'mysql') $query = "SELECT * FROM metar WHERE metar_location = :icao AND metar_date >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 10 HOUR) LIMIT 1";
274
            		else $query = "SELECT * FROM metar WHERE metar_location = :icao AND metar_date >= now() AT TIMEZONE 'UTC' - '10 HOUR'->INTERVAL LIMIT 0,1";
275
                }
276
                $query_values = array(':icao' => $icao);
277
                 try {
278
                        $sth = $this->db->prepare($query);
279
                        $sth->execute($query_values);
280
                } catch(PDOException $e) {
281
                        return "error : ".$e->getMessage();
282
                }
283
                $all = $sth->fetchAll(PDO::FETCH_ASSOC);
284
                if ((!isset($globalMETARcycle) || $globalMETARcycle === false) && count($all) == 0) {
285
            		$all = $this->downloadMETAR($icao);
286
                }
287
                return $all;
288
        }
289
290
       public function addMETAR($location,$metar,$date) {
291
		global $globalDBdriver;
292
		$date = date('Y-m-d H:i:s',strtotime($date));
293
		if ($globalDBdriver == 'mysql') {
294
			$query = "INSERT INTO metar (metar_location,metar_date,metar) VALUES (:location,:date,:metar) ON DUPLICATE KEY UPDATE metar_date = :date, metar = :metar";
295
		} else {
296
			$query = "UPDATE metar SET metar_date = :date, metar = metar WHERE metar_location = :location;INSERT INTO metar (metar_location,metar_date,metar) SELECT :location,:date,:metar WHERE NOT EXISTS (SELECT 1 FROM metar WHERE metar_location = :location);";
297
		}
298
                $query_values = array(':location' => $location,':date' => $date,':metar' => utf8_encode($metar));
299
                 try {
300
                        $sth = $this->db->prepare($query);
301
                        $sth->execute($query_values);
302
                } catch(PDOException $e) {
303
                        return "error : ".$e->getMessage();
304
                }
305
        }
306
307
       public function deleteMETAR($id) {
308
                $query = "DELETE FROM metar WHERE id = :id";
309
                $query_values = array(':id' => $id);
310
                 try {
311
                        $sth = $this->db->prepare($query);
312
                        $sth->execute($query_values);
313
                } catch(PDOException $e) {
314
                        return "error : ".$e->getMessage();
315
                }
316
        }
317
       public function deleteAllMETARLocation() {
318
                $query = "DELETE FROM metar";
319
                 try {
320
                        $sth = $this->db->prepare($query);
321
                        $sth->execute();
322
                } catch(PDOException $e) {
323
                        return "error : ".$e->getMessage();
324
                }
325
        }
326
        
327
        public function addMETARCycle() {
328
    		global $globalDebug, $globalIVAO;
329
    		if (isset($globalDebug) && $globalDebug) echo "Downloading METAR cycle...";
330
    		date_default_timezone_set("UTC");
331
    		$Common = new Common();
332
    		if (isset($globalIVAO) && $globalIVAO) {
333
        		//$cycle = $Common->getData('http://wx.ivao.aero/metar.php');
334
			$Common->download('http://wx.ivao.aero/metar.php',dirname(__FILE__).'/../install/tmp/ivaometar.txt');
0 ignored issues
show
Bug introduced by
The method download() does not seem to exist on object<Common>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
335
    			$handle = fopen(dirname(__FILE__).'/../install/tmp/ivaometar.txt',"r");
336
    		} else {
337
			//$cycle = $Common->getData('http://tgftp.nws.noaa.gov/data/observations/metar/cycles/'.date('H').'Z.TXT');
338
			$Common->download('http://tgftp.nws.noaa.gov/data/observations/metar/cycles/'.date('H').'Z.TXT',dirname(__FILE__).'/../install/tmp/'.date('H').'Z.TXT');
0 ignored issues
show
Bug introduced by
The method download() does not seem to exist on object<Common>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
339
    			$handle = fopen(dirname(__FILE__).'/../install/tmp/'.date('H').'Z.TXT',"r");
340
    		}
341
    		if ($handle) {
342
			if (isset($globalDebug) && $globalDebug) echo "Done - Updating DB...";
343
			$date = '';
344
    			//foreach(explode("\n",$cycle) as $line) {
345
	    		while(($line = fgets($handle,4096)) !== false) {
346
				if (preg_match('#^([0-9]{4})/([0-9]{2})/([0-9]{2}) ([0-9]{2}):([0-9]{2})$#',$line)) {
347
					$date = $line;
348
    				} elseif ($line != '') {
349
    				    //$this->parse($line);
350
    				    if ($date == '') $date = date('Y/m/d H:m');
351
        			    $pos = 0;
352
        			    $pieces = preg_split('/\s/',$line);
353
        			    if ($pieces[0] == 'METAR') $pos++;
354
        			    if (strlen($pieces[$pos]) != 4) $pos++;
355
		        	    $location = $pieces[$pos];
356
        	        	    echo $this->addMETAR($location,$line,$date);
357
    				}
358
    			}
359
    			fclose($handle);
360
    		}
361
    		if (isset($globalDebug) && $globalDebug) echo "Done\n";
362
        
363
        }
364
        public function downloadMETAR($icao) {
365
    		global $globalMETARurl;
366
    		if ($globalMETARurl == '') return array();
367
    		date_default_timezone_set("UTC");
368
    		$Common = new Common();
369
    		$url = str_replace('{icao}',$icao,$globalMETARurl);
370
    		$cycle = $Common->getData($url);
371
    		$date = '';
372
    		foreach(explode("\n",$cycle) as $line) {
373
    			if (preg_match('#^([0-9]{4})/([0-9]{2})/([0-9]{2}) ([0-9]{2}):([0-9]{2})$#',$line)) {
374
    				//echo "date : ".$line."\n";
375
    				$date = $line;
376
    			} 
377
    			if ($line != '') {
378
    			    //$this->parse($line);
379
    			    //echo $line;
380
    			    if ($date == '') $date = date('Y/m/d H:m');
381
    			    $pos = 0;
382
    			    $pieces = preg_split('/\s/',$line);
383
    			    if ($pieces[0] == 'METAR') $pos++;
384
    			    if (strlen($pieces[$pos]) != 4) $pos++;
385
	        	    $location = $pieces[$pos];
386
	        	    if (strlen($location == 4)) {
387
	        		$this->addMETAR($location,$line,$date);
388
	        		return array('0' => array('metar_date' => $date, 'metar_location' => $location, 'metar' => $line));
389
	        	    } else return array();
390
    			}
391
    			//echo $line."\n";
392
    		}
393
    		return array();
394
        
395
        }
396
}
397
/*
398
$METAR = new METAR();
399
echo $METAR->parse('CYZR 070646Z AUTO VRB02KT 1SM R33/3500VP6000FT/ BR OVC001 M03/M03 A3020 RMK ICG PAST HR SLP233');
400
echo $METAR->parse('CYVQ 070647Z 00000KT 10SM -SN OVC030 M24/M26 A2981 RMK SC8 SLP105');
401
echo $METAR->parse('CYFC 070645Z AUTO 23003KT 5/8SM R09/3500VP6000FT BR FEW180 M01/M01 A3004 RMK SLP173');
402
echo $METAR->parse('ZMUB 070700Z VRB01MPS 6000NW SCT100 M11/M15 Q1013 NOSIG RMK QFE652.8 71 NW MO');
403
echo $METAR->parse('LFLY 070700Z AUTO 00000KT 2800 0500 R34/0600D BCFG NSC 04/03 Q1033');
404
echo $METAR->parse('LFLY 071100Z 0712/0812 15007KT CAVOK PROB30 0800/0806 4000 BR');
405
echo $METAR->parse('LFMU 070700Z AUTO 02005KT 5000 BR BKN012/// BKN018/// BKN030/// ///CB 11/11 Q1032');
406
echo $METAR->parse('METAR LFPO 231027Z AUTO 24004G09MPS 2500 1000NW R32/0400 R08C/0004D +FZRA VCSN //FEW015 17/10 Q1009 REFZRA WS R03');
407
*/
408
/*
409
$METAR = new METAR();
410
$METAR->addMETARCycle();
411
*/
412
/*
413
2015/12/07 12:21
414
TAF LFLY 071100Z 0712/0812 15007KT CAVOK PROB30 0800/0806 4000 BR 
415
      BECMG 0805/0807 0400 FG VV/// 
416
     FM081002 18010KT CAVOK
417
     */
418
419
?>