#!/usr/bin/perl -w # NAME: cmpapfreqs.pl # AIM: Give two apt.dat files, collect and compare frequencies listed for each airport # handle 850 and 1000 apt.dat formats use strict; use warnings; use File::Basename; # split path ($name,$dir,$ext) = fileparse($file [, qr/\.[^.]*/] ) use Cwd; my $os = $^O; my $perl_dir = '/home/geoff/bin'; my $PATH_SEP = '/'; my $temp_dir = '/tmp'; if ($os =~ /win/i) { $perl_dir = 'C:\GTools\perl'; $temp_dir = $perl_dir; $PATH_SEP = "\\"; } unshift(@INC, $perl_dir); require 'lib_utils.pl' or die "Unable to load 'lib_utils.pl' Check paths in \@INC...\n"; require 'fg_wsg84.pl' or die "Unable to load fg_wsg84.pl ...\n"; # log file stuff our ($LF); my $pgmname = $0; if ($pgmname =~ /(\\|\/)/) { my @tmpsp = split(/(\\|\/)/,$pgmname); $pgmname = $tmpsp[-1]; } my $outfile = $temp_dir.$PATH_SEP."temp.$pgmname.txt"; open_log($outfile); # user variables my $VERS = "0.0.1 2013-03-17"; my $load_log = 0; my $ap_file1 = 'C:\FG\fgdata\Airports\apt.dat.gz'; my $ap_file2 = 'D:\FG\xplane\1000\apt.dat'; my $verbosity = 0; my $out_file = ''; # ### DEBUG ### my $debug_on = 0; my $def_file = 'def_file'; ### program variables my @warnings = (); my $cwd = cwd(); my $max_lat_len = 0; my $max_lon_len = 0; my $max_alt_len = 0; my $max_nam_len = 0; my $bgntm = time(); sub VERB1() { return $verbosity >= 1; } sub VERB2() { return $verbosity >= 2; } sub VERB5() { return $verbosity >= 5; } sub VERB9() { return $verbosity >= 9; } sub show_warnings($) { my ($val) = @_; if (@warnings) { prt( "\nGot ".scalar @warnings." WARNINGS...\n" ); foreach my $itm (@warnings) { prt("$itm\n"); } prt("\n"); } else { prt( "\nNo warnings issued.\n\n" ) if (VERB9()); } } sub pgm_exit($$) { my ($val,$msg) = @_; if (length($msg)) { $msg .= "\n" if (!($msg =~ /\n$/)); prt($msg); } show_warnings($val); my $secs = time() - $bgntm; prt("Ran for $secs seconds...\n"); close_log($outfile,$load_log); exit($val); } sub prtw($) { my ($tx) = shift; $tx =~ s/\n$//; prt("$tx\n"); push(@warnings,$tx); } sub process_in_file($) { my ($inf) = @_; if (! open INF, "<$inf") { pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); } my @lines = ; close INF; my $lncnt = scalar @lines; prt("Processing $lncnt lines, from [$inf]...\n"); my ($line,$inc,$lnn); $lnn = 0; foreach $line (@lines) { chomp $line; $lnn++; if ($line =~ /\s*#\s*include\s+(.+)$/) { $inc = $1; prt("$lnn: $inc\n"); } } } # versions line # 12345678901234567890123456789012345678901234567890123456789012345678901 # 1000 Version - data cycle 2012.08, build 20121293, metadata AptXP1000 sub load_ap_file($$$) { my ($file,$rv,$rl) = @_; prt("Loading file $file... "); if ($file =~ /\.gz$/) { open IF, "gzip -d -c $file|" or pgm_exit(1, "ERROR: CAN NOT OPEN $file ... $!\n" ); } else { open IF, "<$file" or pgm_exit(1, "ERROR: CAN NOT OPEN $file ... $!\n" ); } my @lines = ; close IF; my $cnt = scalar @lines; prt("got $cnt lines...\n"); pgm_exit(1,"Invalid apt.dat file... too few lines...\n") if ($cnt < 4); my $line = $lines[1]; chomp $line; if ($line =~ /^(\d+)\s+Version\s+/) { ${$rv} = $1; prt("Version $1\n"); } else { pgm_exit(1,"Invalid apt.dat file... no version line...\n"); } $line = substr($line,0,69); prt("$line\n"); ${$rl} = $line; return \@lines; } sub in_world_range($$) { my ($lat,$lon) = @_; if (($lat <= 90)&& ($lat >= -90)&& ($lon <= 180)&& ($lon >= -180)) { return 1; } return 0; } # sort per ASCII in 2nd column - ICAO sub mycmp_ascend_a1 { return -1 if (${$a}[1] lt ${$b}[1]); return 1 if (${$a}[1] gt ${$b}[1]); return 0; } # types of airport - of course some are mix, but my $land_type = 1; my $heli_type = 2; # has a '[H]' in name my $sea_type = 4; # has a '[S]' in name my $aband_type = 8; # has a '[X]' in name sub process_810_lines($) { my $ra = shift; my ($i,$lncnt,$line,@arr,$acnt,$type,$lnn,$apt,$len,@arr2); my ($aalt,$actl,$abld,$icao,$name,$alat,$alon,$glat,$glon); my ($rlat,$rlon,$rwyt,$rwycn,$ftyp,$cfrq,$frqn,$add,$rwycnt,$atyp); $lncnt = scalar @{$ra}; prt("Process $lncnt lines in 810 format...\n"); $lnn = 2; $apt = ''; my @airports = (); my @runways = (); my @waterways = (); my @heliways = (); my @freqs = (); $glat = 0; $glon = 0; my $twrcount = 0; my $wscount = 0; my $freqcount = 0; for ($i = 2; $i < $lncnt; $i++) { $lnn++; $line = ${$ra}[$i]; chomp $line; $line = trim_all($line); $len = length($line); next if ($len == 0); @arr = split(/\s+/,$line); $acnt = scalar @arr; $type = $arr[0]; if ( !($type =~ /^\d+$/) ) { prt("WHAT IS THIS [$line]!\n"); next; } if ($type == 99) { prt("$lnn: Last line...\n"); last; } # 810 format if (($type == 1)||($type == 16)||($type == 17)) { # start with 1, 16, 17 # 0 1 2 3 4 # 17 126 0 0 EH0001 [H] VU medisch centrum # ID ALT C B NAME++ if (length($apt)) { # deal with the previous airport @arr2 = split(/\s+/,$apt); $aalt = $arr2[1]; # Airport (general) ALTITUDE AMSL $actl = $arr2[2]; # control tower $abld = $arr2[3]; # buildings $icao = $arr2[4]; # ICAO $rwyt = $arr2[5]; $name = join(' ', splice(@arr2,5)); # Name # decide if HELI OR SEAPLANE $atyp = $land_type; if ($name =~ /\[H\]/) { @heliways = @runways; @runways = (); $atyp = $heli_type; } elsif ($name =~ /\[S\]/) { @waterways = @runways; @runways = (); $atyp = $sea_type; } if ($name =~ /\[X\]/) { $atyp |= $aband_type; } my @ra = @runways; my @wa = @waterways; my @ha = @heliways; my @fa = @freqs; $alat = 0; $alon = 0; my %info = (); $info{twrcount} = $twrcount; $info{wscount} = $wscount; $info{freqcount} = $freqcount; if ($rwycnt > 0) { $alat = $glat / $rwycnt; $alon = $glat / $rwycnt; } else { prtw("WARNING: $lnn: Ap with NO runways!\n$apt\n"); } # 0 1 2 3 4 5 6 7 8 9 10 11 push(@airports, [$aalt, $icao, $name, $alat, $alon, \@ra, \@wa, \@ha, \@fa, 0, $atyp, \%info ]); # set up minimum display sizes $len = length($aalt); $max_alt_len = $len if ($len > $max_alt_len); $len = length($alat); $max_lat_len = $len if ($len > $max_lat_len); $len = length($alon); $max_lon_len = $len if ($len > $max_lon_len); $len = length($name); $max_nam_len = $len if ($len > $max_nam_len); } # start a NEW airport $apt = $line; @runways = (); # clear RUNWAY list @waterways = (); @heliways = (); @freqs = (); # clear frequencies $glat = 0; $glon = 0; $rwycnt = 0; $twrcount = 0; $wscount = 0; $freqcount = 0; } elsif ($type == 10) { # 810 format # 10 36.962213 127.031071 14x 131.52 8208 1595.0620 0000.0000 150 321321 1 0 3 0.25 0 0300.0300 # 10 36.969145 127.020106 xxx 221.51 329 0.0 0.0 75 161161 1 0 0 0.25 0 $rlat = $arr[1]; $rlon = $arr[2]; $rwyt = $arr[3]; # text 'xxx'=taxiway, 'H1x'=heleport, else a runway ###prt( "$line [$rlat, $rlon]\n" ); if ( $rwyt ne "xxx" ) { # $rwyt =~ s/x//g; # remove trailing 'x' $glat += $rlat; $glon += $rlon; push(@runways, \@arr); $rwycnt++; } ###} elsif ($line =~ /^5(\d+)\s+/) { } elsif (($type >= 50)&&($type <= 56)) { # frequencies $ftyp = $type - 50; $cfrq = $arr[1]; $frqn = $arr[2]; $add = 0; if ($ftyp == 0) { $add = 1; # ATIS } elsif ($ftyp == 1) { $add = 1; # Unicom } elsif ($ftyp == 2) { $add = 1; # clearance } elsif ($ftyp == 3) { $add = 1; # ground } elsif ($ftyp == 4) { $add = 1; # tower } elsif ($ftyp == 5) { $add = 1; # approach } elsif ($ftyp == 6) { $add = 1; # departure } else { pgm_exit(1,"Unknown [$line]\n"); } if ($add) { #push(@freqs, \@arr); # save the freq array push(@freqs, [@arr]); # save the freq array $freqcount++; } else { pgm_exit(1, "WHAT IS THIS [5$ftyp $cfrq $frqn] [$line]\n FIX ME!!!"); } } elsif ($type == 14) { # tower location # 14 52.911007 156.878342 0 0 Tower Viewpoint $twrcount++; } elsif ($type == 15) { # ramp startup } elsif ($type == 18) { # Airport light beacon } elsif ($type == 19) { # Airport windsock # 19 52.911030 156.851840 1 WS $wscount++; } else { prt("FIX ME - LINE UNCASED $type\n"); prt("$line\n"); pgm_exit(1,""); } # 810 format } # get LAST if (length($apt)) { # deal with the previous airport @arr2 = split(/\s+/,$apt); $aalt = $arr2[1]; # Airport (general) ALTITUDE AMSL $actl = $arr2[2]; # control tower $abld = $arr2[3]; # buildings $icao = $arr2[4]; # ICAO $name = join(' ', splice(@arr2,5)); # Name # decide if HELI OR SEAPLANE $atyp = $land_type; if ($name =~ /\[H\]/) { @heliways = @runways; @runways = (); $atyp = $heli_type; } elsif ($name =~ /\[S\]/) { @waterways = @runways; @runways = (); $atyp = $sea_type; } if ($name =~ /\[X\]/) { $atyp |= $aband_type; } $alat = 0; $alon = 0; if ($rwycnt > 0) { $alat = $glat / $rwycnt; $alon = $glat / $rwycnt; } else { prtw("WARNING: $lnn: Ap with NO runways!\n$apt\n"); } my @ra = @runways; my @wa = @waterways; my @ha = @heliways; my @fa = @freqs; my %info = (); $info{twrcount} = $twrcount; $info{wscount} = $wscount; $info{freqcount} = $freqcount; # 0 1 2 3 4 5 6 7 8 9 10 11 push(@airports, [$aalt, $icao, $name, $alat, $alon, \@ra, \@wa, \@ha, \@fa, 0, $atyp, \%info ]); # set up minimum display sizes $len = length($aalt); $max_alt_len = $len if ($len > $max_alt_len); $len = length($alat); $max_lat_len = $len if ($len > $max_lat_len); $len = length($alon); $max_lon_len = $len if ($len > $max_lon_len); $len = length($name); $max_nam_len = $len if ($len > $max_nam_len); } @airports = sort mycmp_ascend_a1 @airports; $aalt = scalar @airports; prt("Collected $aalt airports...\n"); my %h = (); $h{form} = 810; $h{apts} = \@airports; return \%h; } sub process_1000_lines($) { my $ra = shift; my ($i,$lncnt,$line,@arr,$acnt,$type,$lnn,$apt,$len,@arr2); my ($aalt,$actl,$abld,$icao,$name,$alat,$alon,$glat,$glon); my ($rlat1,$rlon1,$rlat2,$rlon2,$rlat,$rlon); my ($rwycnt,$wwcnt,$helicnt); my ($ftyp,$cfrq,$frqn,$add,$rwyt,$atyp); $lncnt = scalar @{$ra}; prt("Process $lncnt lines in 1000 format...\n"); $lnn = 2; $apt = ''; my @airports = (); my @runways = (); my @waterways = (); my @heliways = (); my @freqs = (); my $twrcount = 0; my $wscount = 0; my $freqcount = 0; for ($i = 2; $i < $lncnt; $i++) { $lnn++; $line = ${$ra}[$i]; chomp $line; next if ((length($line) == 0)||($line =~ /^\s+$/)); @arr = split(/\s+/,$line); $acnt = scalar @arr; $type = $arr[0]; if ( !($type =~ /^\d+$/) ) { prt("WHAT IS THIS [$line]!\n"); next; } if ($type == 99) { prt("$lnn: Last line...\n"); last; } # 1000 format if (($type == 1)||($type == 16)||($type == 17)) { # start with 1, 16, 17 # 0 1 2 3 4 # 17 126 0 0 EH0001 [H] VU medisch centrum # ID ALT C B NAME++ if (length($apt)) { # deal with the previous airport @arr2 = split(/\s+/,$apt); $aalt = $arr2[1]; # Airport (general) ALTITUDE AMSL $actl = $arr2[2]; # control tower $abld = $arr2[3]; # buildings $icao = $arr2[4]; # ICAO $name = join(' ', splice(@arr2,5)); # Name $alat = 0; $alon = 0; $rwycnt += $wwcnt; $rwycnt += $helicnt; if ($rwycnt > 0) { $alat = $glat / $rwycnt; $alon = $glat / $rwycnt; } else { prtw("WARNING: $lnn: Ap with NO runways!\n$apt\n"); } # decide if HELI OR SEAPLANE $atyp = $land_type; if ($name =~ /\[H\]/) { $atyp = $heli_type; } elsif ($name =~ /\[S\]/) { $atyp = $sea_type; } if ($name =~ /\[X\]/) { $atyp |= $aband_type; } my @ra = @runways; my @wa = @waterways; my @ha = @heliways; my @fa = @freqs; my %info = (); $info{twrcount} = $twrcount; $info{wscount} = $wscount; $info{freqcount} = $freqcount; # 0 1 2 3 4 5 6 7 8 9 10 11 push(@airports, [$aalt, $icao, $name, $alat, $alon, \@ra, \@wa, \@ha, \@fa, 0, $atyp, \%info ]); # set up minimum display sizes $len = length($aalt); $max_alt_len = $len if ($len > $max_alt_len); $len = length($alat); $max_lat_len = $len if ($len > $max_lat_len); $len = length($alon); $max_lon_len = $len if ($len > $max_lon_len); $len = length($name); $max_nam_len = $len if ($len > $max_nam_len); } # start a NEW airport $apt = $line; @runways = (); # clear RUNWAY list @freqs = (); # clear frequencies $glat = 0; $glon = 0; $rwycnt = 0; $wwcnt = 0; $helicnt = 0; $twrcount = 0; $wscount = 0; $freqcount = 0; } elsif ($type == 10) { # 10 36.962213 127.031071 14x 131.52 8208 1595.0620 0000.0000 150 321321 1 0 3 0.25 0 0300.0300 # 10 36.969145 127.020106 xxx 221.51 329 0.0 0.0 75 161161 1 0 0 0.25 0 $rlat = $arr[1]; $rlon = $arr[2]; $rwyt = $arr[3]; # text 'xxx'=taxiway, 'H1x'=heleport, else a runway ###prt( "$line [$rlat, $rlon]\n" ); if ( $rwyt ne "xxx" ) { # $rwyt =~ s/x//g; # remove trailing 'x' $glat += $rlat; $glon += $rlon; push(@runways, \@arr); $rwycnt++; } } elsif ($type == 100) { # 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 # 100 29.87 3 0 0.00 0 0 0 16 -24.20505300 151.89156100 0.00 0.00 1 0 0 0 34 -24.19732300 151.88585300 0.00 0.00 1 0 0 0 # 100 29.87 1 0 0.15 0 2 1 13L 47.53801700 -122.30746100 73.15 0.00 2 0 0 1 31R 47.52919200 -122.30000000 110.95 0.00 2 0 0 1 $rlat1 = $arr[9]; # $of_lat1 $rlon1 = $arr[10]; # $of_lon1 $rlat2 = $arr[18]; # $of_lat2 $rlon2 = $arr[19]; # $of_lon2 $rlat = ($rlat1 + $rlat2) / 2; $rlon = ($rlon1 + $rlon2) / 2; ###prt( "$line [$rlat, $rlon]\n" ); $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@runways, \@a2); $rwycnt++; } elsif ($type == 101) { # Water runways # 0 1 2 3 4 5 6 7 8 # 101 243.84 0 16 29.27763293 -089.35826258 34 29.26458929 -089.35340410 # 101 22.86 0 07 29.12988952 -089.39561501 25 29.13389936 -089.38060001 # prt("$.: $line\n"); $rlat1 = $arr[4]; $rlon1 = $arr[5]; $rlat2 = $arr[7]; $rlon2 = $arr[8]; $rlat = sprintf("%.8f",(($rlat1 + $rlat2) / 2)); $rlon = sprintf("%.8f",(($rlon1 + $rlon2) / 2)); if (!in_world_range($rlat,$rlon)) { prtw( "WARNING: $.: $line [$rlat, $rlon] NOT IN WORLD\n" ); next; } $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@waterways, \@a2); $wwcnt++; } elsif ($type == 102) { # Heliport # my $heli = '102'; # Helipad # 0 1 2 3 4 5 6 7 8 9 10 11 # 102 H2 52.48160046 013.39580674 355.00 18.90 18.90 2 0 0 0.00 0 # 102 H3 52.48071507 013.39937648 2.64 13.11 13.11 1 0 0 0.00 0 # prt("$.: $line\n"); $rlat = sprintf("%.8f",$arr[2]); $rlon = sprintf("%.8f",$arr[3]); if (!in_world_range($rlat,$rlon)) { prtw( "WARNING: $.: $line [$rlat, $rlon] NOT IN WORLD\n" ); next; } $glat += $rlat; $glon += $rlon; my @a2 = @arr; push(@heliways, \@a2); $helicnt++; } elsif (($type >= 50)&&($type <= 56)) { # frequencies $ftyp = $type - 50; $cfrq = $arr[1]; $frqn = $arr[2]; $add = 0; if ($ftyp == 0) { $add = 1; # ATIS } elsif ($ftyp == 1) { $add = 1; # Unicom } elsif ($ftyp == 2) { $add = 1; # clearance } elsif ($ftyp == 3) { $add = 1; # ground } elsif ($ftyp == 4) { $add = 1; # tower } elsif ($ftyp == 5) { $add = 1; # approach } elsif ($ftyp == 6) { $add = 1; # departure } else { pgm_exit(1,"Unknown [$line]\n"); } if ($add) { ##push(@freqs, \@arr); # save the freq array push(@freqs, [@arr]); # save the freq array $freqcount++; } else { pgm_exit(1, "WHAT IS THIS [5$ftyp $cfrq $frqn] [$line]\n FIX ME!!!"); } } elsif ($type == 110) { # 110 Pavement (taxiway or ramp) header Must form a closed loop } elsif ($type == 120) { # 120 Linear feature (painted line or light string) header Can form closed loop or simple string } elsif ($type == 130) { # 130 Airport boundary header Must form a closed loop } elsif ($type == 111) { # 111 Node All nodes can also include a “style” (line or lights) } elsif ($type == 112) { # 112 Node with Bezier control point Bezier control points define smooth curves } elsif ($type == 113) { # 113 Node with implicit close of loop Implied join to first node in chain } elsif ($type == 114) { # 114 Node with Bezier control point, with implicit close of loop Implied join to first node in chain } elsif ($type == 115) { # 115 Node terminating a string (no close loop) No “styles” used } elsif ($type == 116) { # 116 Node with Bezier control point, terminating a string (no close loop) No “styles” used } elsif ($type == 14) { # 14 Airport viewpoint One or none for each airport - TOWER? $twrcount++; } elsif ($type == 15) { # 15 Aeroplane startup location *** Convert these to new row code 1300 *** } elsif ($type == 18) { # 18 Airport light beacon One or none for each airport } elsif ($type == 19) { # 19 Windsock Zero, one or many for each airport $wscount++; } elsif ($type == 20) { # 20 Taxiway sign (inc. runway distance-remaining signs) Zero, one or many for each airport } elsif ($type == 21) { # 21 Lighting object (VASI, PAPI, Wig-Wag, etc.) Zero, one or many for each airport } elsif (($type >= 1000)&&($type <= 1004)) { # 1000 Airport traffic flow Zero, one or many for an airport. Used if following rules met (rules of same type are ORed together, rules of a different type are ANDed together to). First flow to pass all rules is used. # 1001 Traffic flow wind rule One or many for a flow. Multiple rules of same type “ORed” # 1002 Traffic flow minimum ceiling rule Zero or one rule for each flow # 1003 Traffic flow minimum visibility rule Zero or one rule for each flow # 1004 Traffic flow time rule One or many for a flow. Multiple rules of same type “ORed” } elsif (($type >= 1100)&&($type <= 1101)) { # 1100 Runway-in-use arrival/departure constraints First constraint met is used. Sequence matters # 1101 VFR traffic pattern Zero or one pattern for each traffic flow } elsif (($type >= 1200)&&($type <= 1204)) { # 1200 Header indicating that taxi route network data follows # 1201 Taxi route network node Sequencing is arbitrary. Must be part of one or more edges # 1202 Taxi route network edge Must connect two nodes # 1204 Taxi route edge active zone Can refer to up to 4 runway ends } elsif ($type == 1300) { # 1300 Airport location Not explicitly connected to taxi route network } else { prt("FIX ME - LINE UNCASED $type\n"); prt("$line\n"); pgm_exit(1,""); } # 1000 format } # get LAST if (length($apt)) { # deal with the previous airport @arr2 = split(/\s+/,$apt); $aalt = $arr2[1]; # Airport (general) ALTITUDE AMSL $actl = $arr2[2]; # control tower $abld = $arr2[3]; # buildings $icao = $arr2[4]; # ICAO $name = join(' ', splice(@arr2,5)); # Name $alat = 0; $alon = 0; $rwycnt += $wwcnt; $rwycnt += $helicnt; if ($rwycnt > 0) { $alat = $glat / $rwycnt; $alon = $glat / $rwycnt; } else { prtw("WARNING: $lnn: Ap with NO runways!\n$apt\n"); } # decide if HELI OR SEAPLANE $atyp = $land_type; if ($name =~ /\[H\]/) { $atyp = $heli_type; } elsif ($name =~ /\[S\]/) { $atyp = $sea_type; } if ($name =~ /\[X\]/) { $atyp |= $aband_type; } my @ra = @runways; my @wa = @waterways; my @ha = @heliways; my @fa = @freqs; my %info = (); $info{twrcount} = $twrcount; $info{wscount} = $wscount; $info{freqcount} = $freqcount; # 0 1 2 3 4 5 6 7 8 9 10 11 push(@airports, [$aalt, $icao, $name, $alat, $alon, \@ra, \@wa, \@ha, \@fa, 0, $atyp, \%info ]); # set up minimum display sizes $len = length($aalt); $max_alt_len = $len if ($len > $max_alt_len); $len = length($alat); $max_lat_len = $len if ($len > $max_lat_len); $len = length($alon); $max_lon_len = $len if ($len > $max_lon_len); $len = length($name); $max_nam_len = $len if ($len > $max_nam_len); } @airports = sort mycmp_ascend_a1 @airports; $aalt = scalar @airports; prt("Collected $aalt airports...\n"); my %h = (); $h{form} = 1000; $h{apts} = \@airports; return \%h; } # Like # 50 10820 ATIS # 53 11950 DESIDERIO GND # 54 12250 DESIDERIO TWR # 55 12790 OSAN APP/DEP my %off2name = ( 0 => 'ATIS', 1 => 'Unicom', 2 => 'Clearance', 3 => 'Ground', 4 => 'Tower', 5 => 'Approach', 6 => 'Departure' ); my %off2sname = ( 50 => 'ATIS', 51 => 'Unicom', 52 => 'CLR', 53 => 'GND', 54 => 'TWR', 55 => 'APP', 56 => 'DEP' ); # compare the frequencies show by a particular ICAO value my %compared_icao = (); sub compare_freq_ra($$$$) { my ($ra1,$ra2,$rni2,$rni1) = @_; my ($aalt,$icao,$name,$alat,$alon,$rra,$rwa,$rha,$rfa); my ($aalt2,$icao2,$name2,$alat2,$alon2,$rra2,$rwa2,$rha2,$rfa2); $aalt = ${$ra1}[0]; $icao = ${$ra1}[1]; $name = ${$ra1}[2]; $alat = ${$ra1}[3]; $alon = ${$ra1}[4]; $rra = ${$ra1}[5]; $rwa = ${$ra1}[6]; $rha = ${$ra1}[7]; $rfa = ${$ra1}[8]; $aalt2 = ${$ra2}[0]; $icao2 = ${$ra2}[1]; $name2 = ${$ra2}[2]; $alat2 = ${$ra2}[3]; $alon2 = ${$ra2}[4]; $rra2 = ${$ra2}[5]; $rwa2 = ${$ra2}[6]; $rha2 = ${$ra2}[7]; $rfa2 = ${$ra2}[8]; my $fcnt1 = scalar @{$rfa}; my $fcnt2 = scalar @{$rfa2}; my ($i,$j); my ($type,$type2,$freq,$freq2,$fnd); my @nfin2 = (); my @nfin1 = (); for ($i = 0; $i < $fcnt1; $i++) { $type = ${$rfa}[$i][0]; $freq = ${$rfa}[$i][1]; $fnd = 0; for ($j = 0; $j < $fcnt2; $j++) { $type2 = ${$rfa2}[$j][0]; $freq2 = ${$rfa2}[$j][1]; if (($type == $type2)&&($freq == $freq2)) { $fnd = 1; last; } } if (!$fnd) { push(@nfin2,$i); push(@{$rni2}, $i); } } for ($i = 0; $i < $fcnt2; $i++) { $type = ${$rfa2}[$i][0]; $freq = ${$rfa2}[$i][1]; $fnd = 0; for ($j = 0; $j < $fcnt1; $j++) { $type2 = ${$rfa}[$j][0]; $freq2 = ${$rfa}[$j][1]; if (($type == $type2)&&($freq == $freq2)) { $fnd = 1; last; } } if (!$fnd) { push(@nfin1,$i); push(@{$rni1}, $i); } } my $cnt1 = scalar @nfin2; my $cnt2 = scalar @nfin1; my ($acnt,$afcnt,$dname); if ($cnt1) { $icao .= ' ' while (length($icao) < 4); #$alat = ' '.$alat while (length($alat) < $max_lat_len); #$alon = ' '.$alon while (length($alon) < $max_lon_len); #$aalt = ' '.$aalt while (length($aalt) < $max_alt_len); $dname = $name; $dname .= ' ' while (length($dname) < $max_nam_len); $acnt = sprintf("%2d",$cnt1); $afcnt = sprintf("%2d",$fcnt1); prt("$icao $dname has $acnt of $afcnt 1NOTin2 "); foreach $i (@nfin2) { $type = ${$rfa}[$i][0]; $freq = ${$rfa}[$i][1]; $type = $off2sname{$type} if (defined $off2sname{$type}); prt("$type $freq "); push(@{$rni2},$i); # NOT found in 2 } prt("\n"); } if ($cnt2) { if ($cnt1) { $icao2 = ' ' x 4; if ($name eq $name2) { $name2 = ' ' x $max_nam_len; } else { $name2 .= ' ' while (length($name2) < $max_nam_len); } } else { $icao2 .= ' ' while (length($icao2) < 4); #$alat = ' '.$alat while (length($alat) < $max_lat_len); #$alon = ' '.$alon while (length($alon) < $max_lon_len); #$aalt = ' '.$aalt while (length($aalt) < $max_alt_len); $name2 .= ' ' while (length($name2) < $max_nam_len); } $acnt = sprintf("%2d",$cnt2); $afcnt = sprintf("%2d",$fcnt2); prt("$icao2 $name2 has $acnt of $afcnt 2NOTin1 "); foreach $i (@nfin1) { $type = ${$rfa2}[$i][0]; $freq = ${$rfa2}[$i][1]; $type = $off2sname{$type} if (defined $off2sname{$type}); prt("$type $freq "); push(@{$rni1},$i); } prt("\n"); } return ($cnt1 + $cnt2); } # my %h = (); # $h{form} = 810; # $h{apts} = @airports; # return \%h; sub compare_ap_ref_hashs($$) { my ($apth1,$apth2) = @_; if ((!defined ${$apth1}{form})||(!defined ${$apth1}{apts})) { prtw("WARNING: ref hash 1 does not have 'form' or 'apts'\n"); return; } if ((!defined ${$apth2}{form})||(!defined ${$apth2}{apts})) { prtw("WARNING: ref hash 2 does not have 'form' or 'apts'\n"); return; } # ready to party with data my ($apt1,$apt2,$form1,$form2); $form1 = ${$apth1}{form}; $apt1 = ${$apth1}{apts}; $form2 = ${$apth2}{form}; $apt2 = ${$apth2}{apts}; my $acnt1 = scalar @{$apt1}; my $acnt2 = scalar @{$apt2}; ## 0 1 2 3 4 5 6 7 8 9 10 11 #push(@airports, [$aalt, $icao, $name, $alat, $alon, \@ra, \@wa, \@ha, \@fa, 0, $atyp, \%info ]); my ($i,$j,$fnd,$aalt,$icao,$name,$alat,$alon,$rra,$rwa,$rha,$rfa,$atyp); my ($aalt2,$icao2,$name2,$alat2,$alon2,$rra2,$rwa2,$rha2,$rfa2,$atyp2); my ($ra1,$ra2,$msg,$mat2,$rih,$rih2); my @nfin2 = (); my @nfin1 = (); my $diff_cnt = 0; my $same_cnt = 0; my $miss_cnt = 0; my $miss_cnt2 = 0; my @fnotin2 = (); my @fnotin1 = (); my $apnotwr = 0; my $apnows = 0; my $apnofrq = 0; my $apnotwr2 = 0; my $apnows2 = 0; my $apnofrq2 = 0; my $helini2 = 0; my $seani2 = 0; my $helini1 = 0; my $seani1 = 0; # ============================================================ # first compare prt("\nComparing $acnt1 with $acnt2 airports...\n"); for ($i = 0; $i < $acnt1; $i++) { $ra1 = ${$apt1}[$i]; $aalt = ${$apt1}[$i][0]; $icao = ${$apt1}[$i][1]; $name = ${$apt1}[$i][2]; $alat = ${$apt1}[$i][3]; $alon = ${$apt1}[$i][4]; $rra = ${$apt1}[$i][5]; $rwa = ${$apt1}[$i][6]; $rha = ${$apt1}[$i][7]; $rfa = ${$apt1}[$i][8]; # 9 used for cross referencing $atyp = ${$apt1}[$i][10]; # land, heli, sea OR abandoned $rih = ${$apt1}[$i][11]; # contains twrcount, wscount, freqcount $fnd = 0; for ($j = 0; $j < $acnt2; $j++) { $mat2 = ${$apt2}[$j][9]; next if ($mat2 > 0); $icao2 = ${$apt2}[$j][1]; if ($icao eq $icao2) { $fnd = 1; $ra2 = ${$apt2}[$j]; $aalt2 = ${$apt2}[$j][0]; #$icao2 = ${$apt2}[$j][1]; $name2 = ${$apt2}[$j][2]; $alat2 = ${$apt2}[$j][3]; $alon2 = ${$apt2}[$j][4]; $rra2 = ${$apt2}[$j][5]; $rwa2 = ${$apt2}[$j][6]; $rha2 = ${$apt2}[$j][7]; $rfa2 = ${$apt2}[$j][8]; # 9 used for cross referencing ${$apt1}[$i][9] = $j + 1; # matched ${$apt2}[$j][9] = $i + 1; # matched $atyp2 = ${$apt2}[$j][10]; # land, heli, sea OR abandoned $rih2 = ${$apt2}[$j][11]; # contains twrcount, wscount, freqcount last; } } if ($fnd) { if (!defined $compared_icao{$icao}) { $compared_icao{$icao} = 1; if (compare_freq_ra($ra1,$ra2,\@fnotin2,\@fnotin1)) { $diff_cnt++; } else { $same_cnt++; } } } else { $helini2++ if ($atyp & $heli_type); $seani2++ if ($atyp & $sea_type);; $icao .= ' ' while (length($icao) < 4); $alat = ' '.$alat while (length($alat) < $max_lat_len); $alon = ' '.$alon while (length($alon) < $max_lon_len); $aalt = ' '.$aalt while (length($aalt) < $max_alt_len); $name .= ' ' while (length($name) < $max_nam_len); $msg = "$icao $alat $alon $aalt $name"; #prt("$msg NOT found in 2\n"); push(@nfin1,$msg); $miss_cnt++; } $apnotwr++ if (${$rih}{twrcount} == 0); $apnows++ if (${$rih}{wscount} == 0); $apnofrq++ if (${$rih}{freqcount} == 0); } # ============================================================ # second compare - compare 1 with 2 prt("\nComparing $acnt2 with $acnt1 airports...\n"); for ($i = 0; $i < $acnt2; $i++) { $ra2 = ${$apt2}[$i]; $aalt = ${$apt2}[$i][0]; $icao = ${$apt2}[$i][1]; $name = ${$apt2}[$i][2]; $alat = ${$apt2}[$i][3]; $alon = ${$apt2}[$i][4]; $rra = ${$apt2}[$i][5]; $rwa = ${$apt2}[$i][6]; $rha = ${$apt2}[$i][7]; $rfa = ${$apt2}[$i][8]; $mat2 = ${$apt2}[$i][9]; $atyp = ${$apt2}[$i][10]; # land, heli, sea OR abandoned $rih2 = ${$apt2}[$i][11]; # contains twrcount, wscount, freqcount $apnotwr2++ if (${$rih2}{twrcount} == 0); $apnows2++ if (${$rih2}{wscount} == 0); $apnofrq2++ if (${$rih2}{freqcount} == 0); next if ($mat2); $fnd = 0; for ($j = 0; $j < $acnt1; $j++) { $icao2 = ${$apt1}[$j][1]; if ($icao eq $icao2) { $fnd = 1; $ra2 = ${$apt1}[$j]; $aalt2 = ${$apt1}[$j][0]; #$icao2 = ${$apt1}[$j][1]; $name2 = ${$apt1}[$j][2]; $alat2 = ${$apt1}[$j][3]; $alon2 = ${$apt1}[$j][4]; $rra2 = ${$apt1}[$j][5]; $rwa2 = ${$apt1}[$j][6]; $rha2 = ${$apt1}[$j][7]; $rfa2 = ${$apt1}[$j][8]; $atyp2 = ${$apt1}[$j][10]; # land, heli, sea OR abandoned last; } } if ($fnd) { if (!defined $compared_icao{$icao}) { $compared_icao{$icao} = 1; if (compare_freq_ra($ra1,$ra2,\@fnotin2,\@fnotin1)) { $diff_cnt++; } else { $same_cnt++; } } } else { $helini1++ if ($atyp & $heli_type); $seani1++ if ($atyp & $sea_type);; $icao .= ' ' while (length($icao) < 4); $alat = ' '.$alat while (length($alat) < $max_lat_len); $alon = ' '.$alon while (length($alon) < $max_lon_len); $aalt = ' '.$aalt while (length($aalt) < $max_alt_len); $name .= ' ' while (length($name) < $max_nam_len); $msg = "$icao $alat $alon $aalt $name"; #prt("$msg NOT found in 2\n"); push(@nfin1,$msg); $miss_cnt2++; } } $fnd = scalar @nfin2; prt("Have $fnd of $acnt1 NOT found in 2, heli $helini2, sea $seani2\n"); if ($fnd) { prt(join("\n",@nfin2)."\n"); } $fnd = scalar @nfin1; prt("Have $fnd of $acnt2 NOT found in 1, heli $helini1, sea $seani1\n"); if ($fnd) { prt(join("\n",@nfin1)."\n"); } $fnd = scalar @fnotin2; if ($fnd) { prt("Found $fnd cases of frequencies not in 2\n"); } $fnd = scalar @fnotin1; if ($fnd) { prt("Found $fnd cases of frequencies not in 1\n"); } prt("In comparing $acnt1 with $acnt2 airports... same $same_cnt, diff $diff_cnt, miss 1IN2 $miss_cnt, miss 2IN1 $miss_cnt2\n"); prt("$acnt1 AP1 no twr $apnotwr, ws $apnows, f $apnofrq, $acnt2 AP2 no twr $apnotwr2, ws $apnows2, f $apnofrq2\n"); $fnd = scalar @nfin2; prt("Have $fnd of $acnt1 $ap_file1 airports NOT found in 2, heli $helini2, sea $seani2\n"); $fnd = scalar @nfin1; prt("Have $fnd of $acnt2 $ap_file2 airports NOT found in 1, heli $helini1, sea $seani1\n"); } sub load_ap_files() { my ($v1,$v2,$ln1,$ln2); my $ra1 = load_ap_file($ap_file1,\$v1,\$ln1); my ($raph1,$raph2); if ($v1 == 810) { $raph1 = process_810_lines($ra1); } elsif ($v1 == 1000) { $raph1 = process_1000_lines($ra1); } else { pgm_exit(1,"ERROR: Uncoded version [$v1]\n"); } my $ra2 = load_ap_file($ap_file2,\$v2,\$ln2); if ($v2 == 810) { $raph2 = process_810_lines($ra2); } elsif ($v2 == 1000) { $raph2 = process_1000_lines($ra2); } else { pgm_exit(1,"ERROR: Unknown version [$v2]\n"); } compare_ap_ref_hashs($raph1,$raph2); } ######################################### ### MAIN ### parse_args(@ARGV); load_ap_files(); #process_in_file($in_file); $load_log = 1; pgm_exit(0,""); ######################################## sub need_arg { my ($arg,@av) = @_; pgm_exit(1,"ERROR: [$arg] must have a following argument!\n") if (!@av); } sub parse_args { my (@av) = @_; my ($arg,$sarg); while (@av) { $arg = $av[0]; if ($arg =~ /^-/) { $sarg = substr($arg,1); $sarg = substr($sarg,1) while ($sarg =~ /^-/); if (($sarg =~ /^h/i)||($sarg eq '?')) { give_help(); pgm_exit(0,"Help exit(0)"); } elsif ($sarg =~ /^v/) { if ($sarg =~ /^v.*(\d+)$/) { $verbosity = $1; } else { while ($sarg =~ /^v/) { $verbosity++; $sarg = substr($sarg,1); } } prt("Verbosity = $verbosity\n") if (VERB1()); } elsif ($sarg =~ /^l/) { if ($sarg =~ /^ll/) { $load_log = 2; } else { $load_log = 1; } prt("Set to load log at end. ($load_log)\n") if (VERB1()); } elsif ($sarg =~ /^o/) { need_arg(@av); shift @av; $sarg = $av[0]; $out_file = $sarg; prt("Set out file to [$out_file].\n") if (VERB1()); } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } } else { pgm_exit(1,"ERROR: Invalid argument [$arg]! Try -?\n"); } shift @av; } if ($debug_on) { prtw("WARNING: DEBUG is ON!\n"); } pgm_exit(1,"ERROR: Can NOT locate $ap_file1!\n") if (! -f $ap_file1); pgm_exit(1,"ERROR: Can NOT locate $ap_file2!\n") if (! -f $ap_file2); } sub give_help { prt("$pgmname: version $VERS\n"); prt("Usage: $pgmname [options] in-file\n"); prt("Options:\n"); prt(" --help (-h or -?) = This help, and exit 0.\n"); prt(" --verb[n] (-v) = Bump [or set] verbosity. def=$verbosity\n"); prt(" --load (-l) = Load LOG at end. ($outfile)\n"); prt(" --out (-o) = Write output to this file.\n"); } # eof - cmpapfreq.pl