#!/usr/bin/perl -w
# NAME: chkcflog.pl
# AIM: Read and show details from the cf_client LOG file
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";
# 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 2012-07-18";
my $load_log = 0;
my $in_file = '';
my $verbosity = 0;
my $out_file = '';

# ### DEBUG ###
my $debug_on = 1;
#my $def_file = 'C:\FG\17\build-cft\cft-log4.txt'; # full log at dist 2000
#my $def_file = 'C:\FG\17\build-cft\cft-log3.txt'; # full log at dist 200
#my $def_file = 'C:\FG\17\build-cft\cft-log2.txt'; # full log at dist 100
#my $def_file = 'C:\FG\17\build-cft\cft-log1.txt'; # short log
my $def_file = 'C:\FG\17\build-cft\tempcft.txt';

# Processing 631820 lines, from [C:\FG\17\build-cft\tempcft.txt]...
# Ignoring 343 NEW, from 628784 of 631820 CHG lines, got 5 headers...
# HDGC 58893 SPDC 2141 TIME 38786 ALTC 739 DIST 528225

### program variables
my @warnings = ();
my $cwd = cwd();

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);
    close_log($outfile,$load_log);
    exit($val);
}


sub prtw($) {
   my ($tx) = shift;
   $tx =~ s/\n$//;
   prt("$tx\n");
   push(@warnings,$tx);
}

my %leads = (
    'HDGC' => 1,
    'SPDC' => 1,
    'NEW' => 0,
    'TIME' => 1,
    'ALTC' => 1,
    'DIST' => 1,
    'STAT' => 0,
    'REVIVED' => 0
);

sub process_in_file($) {
    my ($inf) = @_;
    if (! open INF, "<$inf") {
        pgm_exit(1,"ERROR: Unable to open file [$inf]\n"); 
    }
    my @lines = <INF>;
    close INF;
    my $lncnt = scalar @lines;
    prt("Processing $lncnt lines, from [$inf]...\n");
    my ($line,$itm,$lnn,@arr,$uitm,$len,$i,$ch,$tag,$cnt);
    my ($hcnt,$ncnt,@ar,$pkts,$disc,$tot,$pct,$cs,$rh,$msg,$scnt,$prev,$air,$key);
    my ($expcnt,$tpct,$dpct,$minpct,$maxpct,$minmsg,$maxmsg);
    $lnn = 0;
    my %headers = ();
    my %records = ();
    my %callsigns = ();
    my %aircrafts = ();
    $hcnt = 0;
    $ncnt = 0;
    $scnt = 0;
    $pkts = 0;
    $disc = 0;
    $tot = 0;
    $expcnt = 0;
    my $maxalen = 0;
    foreach $line (@lines) {
        chomp $line;
        $lnn++;
        @arr = space_split($line);
        $itm = $arr[0];
        $uitm = uc($itm);
        if ($uitm eq $itm) {
            $len = length($itm);
            $tag = '';
            for ($i = 0; $i < $len; $i++) {
                $ch = substr($itm,$i,1);
                if ($ch =~ /[A-Z]/) {
                    $tag .= $ch;
                } else {
                    last;
                }
            }
            if (length($tag)) {
                if ($tag eq 'NEW') {
                    $ncnt++;
                } elsif ($tag eq 'STAT') {
                    $scnt++;
                } elsif ($tag eq 'REVIVED') {
                    $ncnt++;
                } elsif ($tag eq 'EXPIRED') {
                    $expcnt++;
                } else {
                    $hcnt++;
                    $cs = $arr[1];
                    if (defined $headers{$tag}) {
                        $headers{$tag}++;
                    } else {
                        $headers{$tag} = 1;
                    }
                    $air = '';
                    $prev = '';
                    foreach $itm (@arr) {
                        # pkts=264/200
                        if ($itm =~ /^pkts=/) {
                            $air = $prev;
                            $len = length($air);
                            $maxalen = $len if ($len > $maxalen);
                            $uitm = substr($itm,5);
                            #prt("$uitm ");
                            @ar = split(/\//,$uitm);
                            $pkts += $ar[0];
                            $disc += $ar[1];
                            $key = "$cs;$air";
                            $records{$key} = {} if (!defined $records{$key});
                            $rh = $records{$key};
                            ${$rh}{'packets'} = $ar[0];
                            ${$rh}{'discard'} = $ar[1];
                            # keep aircraft per callsign and callsigns
                            $callsigns{$cs} = {} if (!defined $callsigns{$cs});
                            $rh = $callsigns{$cs};
                            if (defined ${$rh}{$air}) {
                                ${$rh}{$air}++;
                            } else {
                                ${$rh}{$air} = 1;
                            }
                            # keep callsign per aircraft in aircrafts
                            $aircrafts{$air} = {} if (!defined $aircrafts{$air});
                            $rh = $aircrafts{$air};
                            if (defined ${$rh}{$cs}) {
                                ${$rh}{$cs}++;
                            } else {
                                ${$rh}{$cs} = 1;
                            }
                            last;
                        }
                        $prev = $itm;
                    }
                }
            }
        }
    }
    $len = scalar keys(%headers);
    prt("Ignoring $ncnt NEW, $scnt STAT, from $hcnt of $lnn CHG lines, got $len headers...\n");
    $tot = 0;
    foreach $itm (keys %headers) {
        $len = $headers{$itm};
        $tot += $len;
    }
    $tpct = 0;
    foreach $itm (keys %headers) {
        $len = $headers{$itm};
        $dpct = (($len / $tot) * 100);
        $pct = int($dpct + 0.5);
        $tpct += $dpct;
        $msg = sprintf("%6d %2d", $len, $pct);
        #prt("$itm $len $pct\% ");
        prt("$itm $msg\% \n");
    }
    prt("Total $tot packets kept. (".int($tpct + 0.5).")\n");
    $tot = $pkts + $disc;
    $pct = int(($disc / $tot) * 100);
    ###prt("Using current eliminaion discarded $disc, $pct\%, db $pkts, of tot $tot\n");
    $len = scalar keys(%records);
    $msg = "Found $len callsign-aircraft. ";
    $len = scalar keys(%callsigns);
    $msg .= "$len callsigns ";
    $len = scalar keys(%aircrafts);
    $msg .= "$len aircrafts ";
    prt("$msg\n");
    my $tot_disc = 0;
    my $tot_kept = 0;
    $minpct = 101;
    $maxpct = 0;
    $minmsg = '';
    $maxmsg = '';
    my ($mostpkts,$minpkts,$maxpmsg,$minpmsg);
    $mostpkts = 0;
    $minpkts = 9999999;
    foreach $key (keys %records) {
        $rh = $records{$key};
        @ar = split(";",$key);
        $cs = $ar[0];
        $cnt = scalar @ar;
        $air = '';
        for ($i = 1; $i < $cnt; $i++) {
            $air .= ';' if (length($air));
            $air .= $ar[$i];
        }
        $pkts = ${$rh}{'packets'};
        $disc = ${$rh}{'discard'};
        $tot = $pkts + $disc;
        $dpct = (($disc / $tot) * 100);
        $pct = int($dpct + 0.5);
        $msg = sprintf("\%8s \%".$maxalen."s disc \%6d, \%2d pct, total %6d, kept %6d packets.",
            $cs, $air, $disc, $pct, $tot, $pkts);
        #prt("$cs discarded $disc, $pct\%, of total $tot. Kept $pkts\n");
        prt("$msg\n");
        $tot_disc += $disc;
        $tot_kept += $pkts;
        if ($dpct > $maxpct) {
            $maxpct = $dpct;
            $maxmsg = $msg;
        }
        if ($dpct < $minpct) {
            $minpct = $dpct;
            $minmsg = $msg;
        }
        #  my ($mostpkts,$minpkts,$maxpmsg,$minpmsg);
        if ($tot > $mostpkts) {
            $mostpkts = $tot;
            $maxpmsg = $msg;
        }
        if ($tot < $minpkts) {
            $minpkts = $tot;
            $minpmsg = $msg;
        }

    }
    $cs = 'TOTALS';
    $tot = $tot_kept + $tot_disc;
    $pct = int(($tot_disc / $tot) * 100);
    $msg = sprintf("\%8s discarded \%6d, \%2d pct, of total %6d, kept %6d packets.",
            $cs, $tot_disc, $pct, $tot, $tot_kept);
    prt("$msg\n\n");
    prt("$minmsg\n");
    prt("$maxmsg\n");
    prt("$minpmsg\n");
    prt("$maxpmsg\n\n");
    $tot = scalar keys(%callsigns);
    prt("List of $tot CALLSIGNS, and the aircrafts used...\n");
    foreach $cs (sort keys %callsigns) {
        $rh = $callsigns{$cs};
        @ar = keys %{$rh};
        $msg = sprintf("\%8s ",$cs);
        @ar = sort @ar;
        $msg .= join(" ",@ar);
        prt("$msg\n");
    }
    prt("\n");
    $tot = scalar keys(%aircrafts);
    prt("List of $tot AIRCRAFTS, and the callsigns that used it...\n");
    foreach $air (sort keys %aircrafts) {
        $rh = $aircrafts{$air};
        @ar = keys %{$rh};
        $msg = sprintf("\%".$maxalen."s ",$air);
        @ar = sort @ar;
        $msg .= join(" ",@ar);
        prt("$msg\n");
    }
    prt("\n");
}

# Processing 17729 lines, from [C:\FG\17\build-cft\cft-log1.txt]...
# Ignoring 63 NEW, from 17597 of 17729 CHG lines, got 5 headers...
# HDGC 1577 SPDC 77 TIME 684 ALTC 1 DIST 15258
# Using current eliminaion discarded 376025, db 3500739, of tot 3876764

#########################################
### MAIN ###
parse_args(@ARGV);
process_in_file($in_file);
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 {
            $in_file = $arg;
            prt("Set input to [$in_file]\n") if (VERB1());
        }
        shift @av;
    }

    if ((length($in_file) ==  0) && $debug_on) {
        $in_file = $def_file;
        prt("Set DEFAULT input to [$in_file]\n");
        $load_log = 1;
    }
    if (length($in_file) ==  0) {
        pgm_exit(1,"ERROR: No input files found in command!\n");
    }
    if (! -f $in_file) {
        pgm_exit(1,"ERROR: Unable to find in file [$in_file]! Check name, location...\n");
    }
}

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 <file>  (-o) = Write output to this file.\n");
}

# eof - template.pl
