#!/usr/bin/perl
#
# halfStats:  A half-life log parsing program
# Location:   http://www.uwm.edu/~zachkarp/halfStats
# Author:     Zachary Karpinski
# Email:      zachkarp@csd.uwm.edu
#

# grabs the number of seconds since 1970
my $start =  `date +%s`;
chomp($start);

my $settings = &parseConfig();

&mergeLogs($settings);

my $stats = &createStatsHash($settings);

&setKillsPerDeath($stats);

&writeIndex($settings, $stats, $start);

&cleanup($settings);

sub writeIndex
{
    my $settings = $_[0];
    my $stats = $_[1];
    my $start = $_[2];

    my $index = "$settings->{'htmlDir'}/index.html";

    my $bgc = $settings->{'bgColor'};
    my $fgc = $settings->{'fgColor'};
    my $lc  = $settings->{'linkColor'};
    my $listMax = $settings->{'listMax'};

    my $name = 0;
    my $count = 1;
    my $goodName = 0;
    my $var = 0;

    &printTop($settings);

    open(FILE, ">>$index");
    flock(FILE, 2);

    print FILE "<b>\n";
    print FILE "<table width='90%' border='0'>\n";
    print FILE "<tr bgcolor='#555555'>\n";
    print FILE "<td><b>Rank</b></td>\n";
    print FILE "<td><b>Name</b></td>\n";
    print FILE "<td><b>Total Kills</b></td>\n";
    print FILE "<td><b>Total Deaths</b></td>\n";
    print FILE "<td><b>Kills per Death</b></td>\n";
    #print FILE "<td><b>Skill rating</b></td>\n";
    print FILE "</tr>\n";
    print FILE "</b>\n";

    foreach $name (sort {$stats->{$b}{'kpd'} <=> $stats->{$a}{'kpd'}} keys(%{$stats}))
    {
	if(
	   $stats->{$name}{'total'} > $settings->{'minimumKills'} 
	   && $name ne ""
	   )
	{
	    $goodName = &removeJunk($name);
	    print FILE "<tr>\n";
	    print FILE "<td><b>$count</b></td>\n";
	    print FILE "<td><a href='players/$goodName.html'>$name</a></td>\n";
	    print FILE "<td>$stats->{$name}{'total'}</td>\n";
	    print FILE "<td>$stats->{$name}{'deaths'}</td>\n";
	    print FILE "<td>$stats->{$name}{'kpd'}</td>\n";
	    #print FILE "<td><b>$stats->{$name}{'skill'}</b></td>\n";
	    print FILE "</tr>\n";
	    
	    &writePlayerPage($settings, $stats, $name);

	    $count++;
	}
    }
    print FILE "</table>\n";
    flock(FILE, 8);
    close(FILE);

    if($settings->{'showAwards'} eq "yes")
    {
	&writeAwards($settings, $stats);
    }

    my $thisHost = "error processing hostname";
    my $duText = `du -h $logDir`;
    chomp($duText);

    my ($size, $dot) = split(" ", $duText);

    my $now = `date +%s`;
    chomp($now);

    my $time = $now - $start;

    my $lastRanDate = `date +%m/%d/%Y`;
    my $lastRanTime = `date +%H:%M`;
   
    chomp($lastRanDate);chomp($lastRanTime);

    if($settings->{'hostname'} eq "default")
    {
        $thisHost = `hostname`;
        chomp($thisHost);
    }
    else
    {
        $thisHost = $settings->{'hostname'};
    }

    open(FILE, ">>$index");
    flock(FILE, 2);
    print FILE "<br><br><br>$size of log files processed in $time seconds<br>\n";
    print FILE "halfStats was last ran $lastRanDate at $lastRanTime<br>\n";
    print FILE "The hostname of this machine is: $thisHost<br><br>\n";
    print FILE "<a href='http://www.planethalflife.com/halfStats'>halfStats</a> was written by <a href='MAILTO:zachkarp\@csd.uwm.edu'>Zach Karpinski</a><br><br><br>\n";    
    print FILE "</center></body></html>\n";
    flock(FILE, 8);
    close(FILE);

}

sub writeAwards
{
    my $settings = $_[0];
    my $stats = $_[1];

    my $totalAwards = $settings->{'numberOfAwards'};

    my $count = 1;
    my %high = ();
    my $thisTag = 0;
    my ($weaponTag, $awardTag, $descTag) = ();

        while($count <= $totalAwards)
	{
	    $thisTag = "award$count";
	    ($weaponTag, $awardTag, $descTag) = split(/\;/, $settings->{$thisTag});
	    $weaponTag =~ s/ /_/g;

	    $high{$weaponTag}{'award'} = $awardTag;
	    $high{$weaponTag}{'desc'} = $descTag;
	    $high{$weaponTag}{'uses'} = 0;
	    $high{$weaponTag}{'name'} = "Unclaimed";
	    $count++;
	}

    foreach $key (keys %high)
    {
	foreach $player (keys %{$stats})
	{
	    if($stats->{$player}{'weapons'}{$key} > $high{$key}{'uses'})
	    {
		$high{$key}{'uses'} = $stats->{$player}{'weapons'}{$key};
		$high{$key}{'name'} = $player;
	    }
	}
    }

    open(FILE, ">>$settings->{'htmlDir'}/index.html");
    flock(FILE, 2);
    print FILE "<br><br><br><br>\n";
    print FILE "<table border='1' width='90%'>\n";
    print FILE "<tr bgcolor='$settings->{'fgColor'}'><td align='center'>\n";
    print FILE "<font color='$settings->{'bgColor'}' size='+2'>\n";
    print FILE "Individual Awards for High Weapon Usage\n";
    print FILE "</font></td></tr></table><br>\n";

    print FILE "<table border='0' width='90%'>\n";
    foreach $key (keys %high)
    {
	print FILE "<tr>\n";
        print FILE "<td><i><font face='helvetica' size='+1'>\n";
	print FILE "$high{$key}{'award'}</font></i><br>\n";
        print FILE "<font size='-1'>($high{$key}{'desc'})</font></td>\n";
	if($settings->{'showWeaponImages'} eq "yes")
        {
            print FILE "<td><img src='images/$key.gif' border='0'></td>\n";
        }
        else
        {
            print FILE "<td>$key</td>\n";
        }
	print FILE "<td><b>$high{$key}{'name'}</b></td>\n";
        print FILE "<td><font color='yellow'><b>$high{$key}{'uses'}</b></font></td>\n";
        print FILE "</tr>\n";
    }
    print FILE "</table>\n";
    flock(FILE, 8);
    close(FILE);

}

sub printTop
{
    my $settings = $_[0];
    
    my $index = "$settings->{'htmlDir'}/index.html";
    my $bgc = $settings->{'bgColor'};
    my $fgc = $settings->{'fgColor'};
    my $lc  = $settings->{'linkColor'};

    open(FILE, ">$index");
    flock(FILE, 2);
    print FILE "<html><head><title>\n";
    print FILE "welcome to halfStats running on $settings->{'hostname'}\n";
    print FILE "</title></head>\n";
    print FILE "<body bgcolor='$bgc' text='$fgc' link='$lc' vlink='$lc' alink='$lc'>\n";
    print FILE "<center>$settings->{'serverBanner'}\n";
    print FILE "<table width='90%' border='1'><tr bgcolor='$fgc'>\n";
    print FILE "<td align='center'>\n";
    print FILE "<font color='$bgc' size='+2' face='times'>\n";
    print FILE "<i>Statistical player listing</i>\n";
    print FILE "</font></td></tr></table><br><br>\n";
    flock(FILE, 8);
    close(FILE);
}

sub calculateKillsPerDeath
{
    my $stats = $_[0];
    my $key = 0;
    my $kpd = 0;

    if($stats->{$key}{'deaths'} > 0)
    {
	$kpd = $stats->{$key}{'total'} / $stats->{$key}{'deaths'};
    }
    else 
    {
	$kpd = "N/A";
    }
    return($kpd);
}

sub testHash
{
    my $stats = $_[0];
    my $key = 0;
    my $weapon = 0;
    my $lenTot = 0;

    foreach $key (keys %{$stats})
    {
	$lenTot = $lenTot + (8 * length($key));
	print "Stats for $key\n";
	print "\tTotal frags: $stats->{$key}{'total'}\n";
	print "\tTotal deaths: $stats->{$key}{'deaths'}\n";
	foreach $weapon (keys %{$stats->{$key}{'weapons'}})
	{
	    print "\t\tUsed $weapon $stats->{$key}{'weapons'}{$weapon} times\n";
	}
    }
    print "Total size for keys: ", $lenTot , " bytes\n";
}

sub createStatsHash
{
    my $settings = $_[0];
    
    my @array = ();
    my $line = 0;
    my $month = 0;
    my $day = 0;
    my $year = 0;

    my $mo = `date +%m`;
    my $yr = `date +%Y`;
    chomp($mo);chomp($yr);

    my $obit = 0;
    my %stats = ();
    
    my $name = 0;
    my $victim = 0;
    my $weapon = 0;
    my $wasThisASuicide = 0;

    open(FILE, "<$settings->{'mergedLog'}");
    @array = <FILE>;
    close(FILE);

    foreach $line (@array)
    {
	chomp($line);

	$line =~ /^.{2}(..)\/(..)\/(....)/;
	$month = $1;
	$day   = $2;
	$year  = $3;
	
	#$line =~ /^.{15}(..)\:(..)\:(..)/;#$hour   = $1;#$minute = $2;#$second = $3;
	
	if($month == $mo && $year == $yr)
	{

	    $line =~ /^.{25}\"(.+?)\"/;
	    $name = $1;
	    
	    if($line =~ "self")
	    {
		$line =~ s/self/\"$name\"/g;
		$wasThisASuicide = 1;
	    }
	    elsif($line =~ "by world")
	    {
		$line =~ s/by world/\"$name\"/g;
		$wasThisASuicide = 1;
	    }

	    if($wasThisASuicide == 1 && $settings->{'calcSuicides'} ne "yes")
	    {
		# do nothing
	    }
	    else
	    {
		$line =~ /^.{25}(.+)/;
		$obit = $1;
		
		$obit =~ /^.{1}(.+?)\<(.){1,3}\>\" killed \"(.+?)\<(.){1,3}\>\" with (.+)/;
		$name = $1;
		$victim = $3;
		$weapon = $5;

		if($name ne "" && $victim ne "" && $weapon ne "")
		{
		    $weapon =~ s/ /_/g;

		    if($name ne $victim)
		    {
			$stats{$name}{'total'} = $stats{$name}{'total'} + 1;
		    }

		    $stats{$victim}{'deaths'} = $stats{$victim}{'deaths'} + 1;
		    
		    $stats{$name}{'weapons'}{$weapon} 
		    =
			$stats{$name}{'weapons'}{$weapon} 
		    + 
			1;
		    
		    $stats{$name}{'victims'}{$victim}{'total'} 
		    =
			$stats{$name}{'victims'}{$victim}{'total'}
		    +
			1;
		    
		    $stats{$name}{'victims'}{$victim}{$weapon}
		    =
			$stats{$name}{'victims'}{$victim}{$weapon}
		    +
			1;
		    #&calcSkill($name, $victim, \%stats);
		}
		$stats{$name}{'kpd'} = 0;
	    }
	    $wasThisASuicide = 0;
	}
    }
    return(\%stats);
}


sub cleanup($settings)
{
    system("rm -f $settings->{'mergedLog'}");
    system("rm -f $settings->{'killLog'}");
    system("rm -f $settings->{'tmpFile'}");
}

sub mergeLogs
{
    my $settings = $_[0];
    system("cat $settings->{'logDir'}/*.log | grep 'killed' > $settings->{'mergedLog'}");
}

sub parseConfig
{
    my $dir = `pwd`;
    chomp($dir);
    my $configFile = "$dir/halfStats.cfg";
    my @fileContents = ();
    my ($variable, $value) = ();
    my %config = ();

    open(FILE, "<$configFile") || die "\n\n*** ERROR: $! for $configFile\n\n";
    @fileContents = <FILE>;
    close(FILE);

    foreach $line (@fileContents)
    {
        $line =~ /^.{0}(.)/;
        if($1 ne "#" && $1 ne "")
        {
            chomp($line);
            ($variable, $value) = split(/\=/, $line, 2);
	    $config{$variable} = $value;
        }
        else
        {
            # do nothing, this is a comment
        }
    }
    # these are internal halfStats settings
    $config{'mergedLog'}  = "/tmp/_mergedLog_.$$";
    $config{'killLog'}    = "/tmp/_killLog_.$$";
    $config{'tmpFile'}    = "/tmp/_tmpFile_.$$";

    return(\%config);
}

sub setKillsPerDeath
{
    my $stats = $_[0];
    my $key = 0;
    
    foreach $key (keys %{$stats})
    {
	if($stats->{$key}{'deaths'} > 0)
	{
	    if($stats->{$key}{'total'} eq "")
	    {
		$stats->{$key}{'total'} = 0;
	    }
	    $stats->{$key}{'kpd'} 
	    = sprintf("%.2f", ($stats->{$key}{'total'} / $stats->{$key}{'deaths'}));
	}
	else
	{
	    $stats->{$key}{'kpd'} = $stats->{$key}{'total'};
 	}
    }
}

sub removeJunk
{
    my $string = $_[0];
    $string =~ s/(\W)/_/g;
    return($string);
}

sub writePlayerPage
{
    my $settings = $_[0];
    my $stats = $_[1];
    my $player = $_[2];

    my $goodName = &removeJunk($player);

    my $bgc = $settings->{'bgColor'};
    my $fgc = $settings->{'fgColor'};
    my $lc  = $settings->{'linkColor'};

    my $file = "$settings->{'htmlDir'}/players/$goodName.html";

    my $weapon = 0;
    my $count = 1;
    my $percent = 0;
    my $size = 0;
    my $bar = 0;
    my $thisKpd = 0;
    my ($favWeap, $favCount) = ();

    open(PAGE, ">$file");
    flock(PAGE, 2);
    print PAGE "<html><head><title>\n";
    print PAGE "Individual statistics for $player\n";
    print PAGE "</title></head>\n";

    print PAGE "<body bgcolor='$bgc' text='$fgc' link='$lc' vlink='$lc'>\n";

    print PAGE "<br><br><br>\n";
    print PAGE "<center>\n";
    print PAGE "<table width='90%' border='0'><tr><td>\n";
    print PAGE "<font face='helvetica' size='+1'>\n";
    print PAGE "Individual statistics for</font>\n";
    print PAGE "<font face='times' size='+2'><i>$player</i>\n";
    print PAGE "</font></td></tr></table>\n";

    print PAGE "<br><br><br>\n";
    print PAGE "<table width='400' border='0'>\n";
    print PAGE "<tr bgcolor='$fgc'>\n";
    print PAGE "<td><font color='$bgc' face='helvetica'>\n";
    print PAGE "<center><i><b>Kill Total: </i></b>\n";
    print PAGE "$stats->{$player}{'total'}</center>\n";
    print PAGE "</font></td>\n";
    print PAGE "<td><font color='$bgc' face='helvetica'>\n";
    print PAGE "<center><i><b>Death Total: </i></b>\n";
    print PAGE "$stats->{$player}{'deaths'}</center>\n";
    print PAGE "</font></td>\n";
    if($settings->{'calcSuicides'} eq "yes")
    {
	if($stats->{$player}{'victims'}{$player}{'total'} eq "")
	{
	    $stats->{$player}{'victims'}{$player}{'total'} = 0;
	}
	print PAGE "<td><font color='$bgc' face='helvetica'>\n";
	print PAGE "<center><i><b>Suicide Total: </i></b>\n";
	print PAGE "$stats->{$player}{'victims'}{$player}{'total'}\n";
	print PAGE "</b></i></center>\n";
	print PAGE "</font></td>\n";
    }
    print PAGE "</tr></table>\n";

    print PAGE "<br><br>\n";
   
    print PAGE "<table width='90%' border='1'><tr><td align='center'>\n";
    print PAGE "<font face='times' size='+2'>Weapon usage chart</font>\n";
    print PAGE "</td></tr></table>\n";

    print PAGE "<table width='90%' border='0'>\n";
    print PAGE "<tr bgcolor='#555555'>\n";
    print PAGE "<td><b><font color='white'>Rank:</font></b></td>\n";
    print PAGE "<td><b><font color='white'>Weapon:</font></b></td>\n";
    print PAGE "<td><b><font color='white'>Number of uses:</font></b></td>\n";
    print PAGE "<td><b><font color='white'>Percentage of kills:</font></b></td>\n";
    print PAGE "<td><b><font color='white'>\%</font></b></td>\n";
    print PAGE "</tr>\n";

    foreach $weapon (sort 
		     { $stats->{$player}{'weapons'}{$b}
		       <=> $stats->{$player}{'weapons'}{$a} }
		     keys %{$stats->{$player}{'weapons'}}
		     )
    {
	if($weapon ne "door"
	   && $weapon ne "rotating"
	   && $weapon ne "trigger_hurt"
	   && $weapon ne "plat"
	   && $weapon ne "worldspawn"
	   && $weapon ne "world"
	   && $weapon ne "env_explosion")
	{

	    print PAGE "<td><b>$count</b></td>\n";
	    if($settings->{'showWeaponImages'} eq "yes")
	    {
		print PAGE "<td><img src='../images/$weapon.gif' border='0'></td>\n";
	    }
	    else
	    {
		print PAGE "<td>$weapon</td>\n";
	    }
	    print PAGE "<td><b>$stats->{$player}{'weapons'}{$weapon}</b></td>\n";

	    if($stats->{$player}{'total'} != 0)
	    {
		$percent = sprintf("%.3f", 
				   ($stats->{$player}{'weapons'}{$weapon}
				    / $stats->{$player}{'total'}));
		$percent = $percent * 100;
	    }
	    else{$percent = "N/A";}

	    if($percent >= 50)
	    {
		$bar = "../images/bar_bright_green.gif";
	    }
	    elsif($percent >= 35)
	    {
		$bar = "../images/bar_dark_green.gif";
	    }
	    elsif($percent >= 20)
	    {
		$bar = "../images/bar_bright_yellow.gif";
	    }
	    elsif($percent >= 10)
	    {
		$bar = "../images/bar_dark_yellow.gif";
	    }
	    elsif($percent >= 5)
	    {
		$bar = "../images/bar_bright_red.gif";
	    }
	    else
	    {
		$bar = "../images/bar_dark_red.gif";
	    }
	    $size = $percent * 3;

	    print PAGE "<td><img src='../images/$bar' border='0' width='$size' height='10'><font color='$fgc'></td>\n";
	    print PAGE "<td><b>$percent\%</b></td>\n";
	    print PAGE "</tr>\n";
	    $count++;
	}
    }
    
    print PAGE "</table>\n";
    print PAGE "<br><br>\n";

    print PAGE "<table width='90%' border='1'><tr><td align='center'>\n";
    print PAGE "<font face='times' size='+2'>Opponent matchup listing</font>\n";
    print PAGE "</td></tr></table>\n";

    print PAGE "<font color='white'>\n";
    print PAGE "<table width='90%' border='0'>\n";
    print PAGE "<tr bgcolor='#555555'>\n";
    print PAGE "<td><b>Name:</b></td>\n";
    print PAGE "<td><b>Losses against $player:</b></td>\n";
    print PAGE "<td><b>Wins against $player:</b></td>\n";
    print PAGE "<td><b>$players's kill to death ratio:</b></td>\n";
    print PAGE "<td><b>Favorite weapon to use:</b></td>\n";
    print PAGE "</tr>\n";
    

    foreach $victim (sort
                     { $stats->{$player}{'victims'}{$b}{'total'}
                       <=> $stats->{$player}{'victims'}{$a}{'total'} }
                     keys %{$stats->{$player}{'victims'}}
                     )
    {
	if($victim ne $player)
	{
	    if($stats->{$victim}{'victims'}{$player}{'total'} eq "")
	    {
		$stats->{$victim}{'victims'}{$player}{'total'} = 0;
	    }
	    if($stats->{$player}{'victims'}{$victim}{'total'} eq "")
	    {
		$stats->{$player}{'victims'}{$victim}{'total'} = 0;
	    }
	    print PAGE "<tr>\n";
	    
	    if($stats->{$victim}{'total'} >= $settings->{'minimumKills'})
	    {
		$goodName = &removeJunk($victim);
		print PAGE "<td><a href='$goodName.html'>$victim</a></td>\n";
	    }
	    else
	    {
		print PAGE "<td>$victim</a></td>\n";
	    }
	    print PAGE "<td>$stats->{$player}{'victims'}{$victim}{'total'}</td>\n";
	    print PAGE "<td>$stats->{$victim}{'victims'}{$player}{'total'}</td>\n";
	    

	    if($stats->{$victim}{'victims'}{$player}{'total'} > 0)
	    {
		$thisKpd = sprintf("%.2f", 
				   ($stats->{$player}{'victims'}{$victim}{'total'}
				    /$stats->{$victim}{'victims'}{$player}{'total'})
				   );
	    }
	    else
	    {
		$thisKpd = "N/A";
	    }
	    print PAGE "<td>$thisKpd</td>\n";
	    
	    if($stats->{$player}{'victims'}{$victim}{'total'} > 0)
	    {
		($favWeap, $favCount) = split(/\,/, &getHighestWeapUsage($player, $victim, $stats));
		if($settings->{'showWeaponImages'} eq "yes")
		{
		    print PAGE "<td><img src='../images/$favWeap.gif' border='0'> x $favCount</td>\n";
		}
		else
		{
		    print PAGE "<td>$favWeap x $favCount</td>\n";
		}
	    }
	    else
	    {
		print PAGE "<td>N/A</td>\n";
	    }
	    print PAGE "</tr>\n";
	}
    }
    print PAGE "</table>\n";
    print PAGE "<br><br><br>\n";

    print PAGE "</center><a href='../index.html'>\n";
    print PAGE "<font size='+2'>Back to Main Player Listing</font>\n";
    print PAGE "</a></body></html>\n";
    flock(PAGE, 8);
    close(PAGE);
}

sub getHighestWeapUsage
{
    my $player = $_[0];
    my $victim = $_[1];
    my $stats = $_[2];
    my $highCount = 0;
    my $highWeap = 0;
    my $weapon = 0;
    
    foreach $weapon (keys %{$stats->{$player}{'victims'}{$victim}})
    {
	if($stats->{$player}{'victims'}{$victim}{$weapon} > $highCount
	   && $weapon ne "total")
	{
	    $highWeap = $weapon;
	    $highCount = $stats->{$player}{'victims'}{$victim}{$weapon};
	}
    }
    return("$highWeap,$highCount");
}
		 
sub calcSkill
{
#For Frags:
#        Killer_Skill=Killer_Skill+((Victim_Skill/Killer_Skill)*10)
#        Victim_skill=Killee_Skill-((Victim_Skill/Killer_Skill)*10)
#
#Deaths:
#        Skill=Skill-10
#
#Suicides
#        Skill=Skill-((Skill/1000)*5)
    my $killer = $_[0];
    my $victim = $_[1];
    my $stats = $_[2];


    if($stats->{$victim}{'skill'} eq "" || $stats->{$victim}{'skill'} == 0)
    {$stats->{$victim}{'skill'} = 1;}

    if($stats->{$killer}{'skill'} eq "" || $stats->{$killer}{'skill'} == 0)
    {$stats->{$killer}{'skill'} = 1;}

    if($killer ne $victim)
    {

	$stats->{$killer}{'skill'} 
	= $stats->{$killer}{'skill'} 
	+ $stats->{$victim}{'skill'}/2;
	    
	$stats->{$victim}{'skill'} 
	= $stats->{$victim}{'skill'}
	- $stats->{$killer}{'skill'}/3;
	
	#$stats->{$victim}{'skill'} = $stats->{$victim}{'skill'} - 10;

    }
    else
    {
	$stats->{$killer}{'skill'} = ($stats->{$killer}{'skill'} 
				      - (($stats->{$killer}{'skill'}/1000) * 5));
    }

    $stats->{$killer}{'skill'} = sprintf("%.1f", $stats->{$killer}{'skill'});
    $stats->{$victim}{'skill'} = sprintf("%.1f", $stats->{$victim}{'skill'});

}   

    
