#!/usr/bin/perl
#
# halfStats:  A half-life log parsing program
# Location:   http://www.planethalflife.com/halfStats
# Author:     Zachary Karpinski
# Email:      zkarpinski@yahoo.com
#

# I promise to program perl well
use strict;

# Set our @ARGV if we have no arguments
if(!@ARGV){ @ARGV = (); }

# Get the time
my @time =  localtime(time);

# Play with the time
my $sec = $time[0];
my $min = $time[1];
my $hour = $time[2];

# Make some Army time..
my $miltime = "$hour$min";

# Give me a big number
my $start = $sec + ($min * 60) + (($hour * 60) * 60);

# Parse the halfStats.cfg
my $settings = &parseConfig(\@ARGV);

# If we are to just report, do that and die
if($ARGV[0]){ if($ARGV[0] eq "-r") { &reportActivity($settings); die "** Reported and quit\n\n"; } }

# Create an array of lines for this period of time
my $array = &mergeLogs($settings, "logs", \@ARGV);

# Create stats from that array
my $stats = &createStatsHash($settings, $array);

&fixSkill($stats);

# If its time to make a connect page, do it
if($miltime >= $settings->{'connectStatStart'}
   && $miltime <= $settings->{'connectStatEnd'}
   && $settings->{'mode'} eq "now"
)
{
    # Make an array for the connect lines
    $array = &mergeLogs($settings, "ips", \@ARGV);

    # Make the Connection Stats page
    &createIPpage($settings, $stats, $array, \@ARGV);
}

# Go through and set all the kill per death ratios
&setKillsPerDeath($stats);

# Write our index.html file
&writeIndex($settings, $stats, $start, \@ARGV);

# If we are announcing, do that
if($settings->{'announce'} eq "on") {&reportActivity($settings);}

# All subroutines are below here
# Anything above this is main

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

    my $index = "$settings->{'skillFile'}";

    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");
    if($settings->{'OS'} eq "unix"){flock(FILE, 2);}

    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";
    if($settings->{'mode'} eq "now")
    {
	print FILE "<td><b><a href='topten-highest_kills.html'>Total Kills</a></b></td>\n";
	print FILE "<td><b><a href='topten-highest_deaths.html'>Total Deaths</a></b></td>\n";
	print FILE "<td><b><a href='topten-highest_kpd.html'>Kills per Death</a></b></td>\n";
    }
    else
    {
	print FILE "<td><b>Total Kills</a></b></td>\n";
	print FILE "<td><b>Total Deaths</a></b></td>\n";
	print FILE "<td><b>Kills per Death</a></b></td>\n";
    }
    print FILE "<td><b><a href='$index'>Skill rating</a></b></td>\n";
    print FILE "</tr>\n";


    foreach $name (keys %{$stats}){ if(!$stats->{$name}{'skill'}){$stats->{$name}{'skill'} = 1000;}}

    foreach $name (sort { $stats->{$b}{'skill'} <=> $stats->{$a}{'skill'} } keys(%{$stats}))
    {	
	if($stats->{$name}{'total'} && $stats->{$name}{'skill'})
	{
	    if($stats->{$name}{'total'} > $settings->{'minimumKills'} 
		&& $count <= $settings->{'listMax'} || $settings->{'listMax'} == 0)
	       {
		if($stats->{$name}{'skill'} >= $settings->{'minimumSkill'})
		{
		    $goodName = &removeJunk($name);
		    print FILE "<tr>\n";
		    print FILE "<td><b>$count</b></td>\n";
		    print FILE "<td><a href='$settings->{'playerDir'}/$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, $ARGS);
	    $count++;
	    #if($settings->{'conserveCPU'} eq "yes") { sleep 1; }
	}
    }
    print FILE "</table>\n";
    if($settings->{'OS'} eq "unix"){flock(FILE, 8);}
    close(FILE);

    if($settings->{'mode'} eq "now")
    {
	&writeTopTenPages($stats, $settings, "$settings->{'killsFile'}", "total");
	&writeTopTenPages($stats, $settings, "$settings->{'kpdFile'}", "kpd");
	&writeTopTenPages($stats, $settings, "$settings->{'deathsFile'}", "deaths");
    }

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

    my $thisHost = "error processing hostname";

    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);


    my $now = $sec + ($min * 60) + (($hour * 60) * 60);

    my $time = $now - $start;

    $mon = $mon + 1;
    $year = $year  + 1900;

    if(length($min) < 2){$min = "0$min";}

    my $lastRanDate = "$mon/$mday/$year";
    my $lastRanTime = "$hour:$min";
   
    $thisHost = $settings->{'hostname'};

    open(FILE, ">>$index");
    if($settings->{'OS'} eq "unix"){flock(FILE, 2);}
    print FILE "<br><br>\n";

    if(!@$ARGS[0])
    {
	if(-e "$settings->{'htmlDir'}/previous.html")
	{
	    print FILE "<SCRIPT language='JavaScript'><!--\nfunction my_win()\n{\nwindow.open('previous.html','previous','width=320,height=200,toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,copyhistory=no,resizable=yes'\)\;}//--></SCRIPT><a href='javascript:my_win()'><img src='images/prevmonths_button.gif' border='0'></a><br>\n";
	}
	
	if($settings->{'pubConnectStats'} eq "1")
	{
	    print FILE "<a href='connect_stats.html' target='_connect'>\n";
	    print FILE "<img src='images/stats_button.gif' border='0'>\n";
	    print FILE "</a><br><br>\n";
	}
    }


    print FILE "$settings->{'logSize'} of log files processed in $time seconds<br>\n";


    print FILE "halfStats was last ran $lastRanDate at $lastRanTime<br>\n";
    my $statsmonth = $settings->{'monthsToUse'} + 1;
    print FILE "Stats are being discarded after <b>$statsmonth</b> months<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:zkarpinski\@yahoo.com'>Zach Karpinski</a><br><br><br>\n";    
    print FILE "</center></body></html>\n";
    if($settings->{'OS'} eq "unix"){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 $key = 0;
    my $player = 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})
	    {
		if($stats->{$player}{'weapons'}{$key} > $high{$key}{'uses'})
		{
		    $high{$key}{'uses'} = $stats->{$player}{'weapons'}{$key};
		    $high{$key}{'name'} = $player;
		}
	    }
	    else
	    {
		$stats->{$player}{'weapons'}{$key} = 0;
	    }
	}
    }

    open(FILE, ">>$settings->{'skillFile'}");
    if($settings->{'OS'} eq "unix"){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";
    if($settings->{'OS'} eq "unix"){flock(FILE, 8);}
    close(FILE);

}

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

    open(FILE, ">$index");
    if($settings->{'OS'} eq "unix"){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 "<br><br><br>\n";
    
    if($settings->{'OS'} eq "unix"){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 createStatsHash
{
    my $settings = $_[0];
    my $array = $_[1];

    my $line = 0;

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

    while($line = shift @$array)
    {
	chomp($line);
	
	
	$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;
	}
	
	$line =~ /^.{25}(.+)/;
	$obit = $1;
	
	$obit =~ /^.{1}(.+?)\<(.+?)\>\" killed \"(.+?)\<(.+?)\>\" with (.+)/;
	$name = $1;
	$victim = $3;
	$weapon = $5;

	if(!$name){ $name = "Player"; }
	if(!$victim){ $victim = "Player"; }
	if(!$weapon){ $weapon = "grenade"; }

	if((length($name) > 0) && (length($victim) > 0) && (length($weapon) > 0))
	{
	    $weapon =~ s/ /_/g;


	    # Initialize this hash if it doesnt exist
	    # Check both victim and killer
	    if(!$stats{$name}){$stats{$name} = ();}
	    if(!$stats{$victim}){$stats{$victim} = ();}
	    
	    # Initialize Killer counters
	    if(!$stats{$name}{'total'})  { $stats{$name}{'total'}  = 0; }
	    if(!$stats{$name}{'deaths'}) { $stats{$name}{'deaths'} = 0; }
	    if(!$stats{$name}{'skill'})  { $stats{$name}{'skill'}  = 1000; }
	    if(!$stats{$name}{'kpd'})    { $stats{$name}{'kpd'}    = 0; }
	    
	    # Initialize Victim counters
	    if(!$stats{$victim}{'total'})  { $stats{$victim}{'total'}  = 0; }
	    if(!$stats{$victim}{'deaths'}) { $stats{$victim}{'deaths'} = 0; }
	    if(!$stats{$victim}{'skill'})  { $stats{$victim}{'skill'}  = 1000; }
	    if(!$stats{$victim}{'kpd'})    { $stats{$victim}{'kpd'}    = 0; }
	    
	    # Initialize memory we will be using
	    if(!$stats{$name}{'weapons'}{$weapon})          { $stats{$name}{'weapons'}{$weapon}          = 0; }
	    if(!$stats{$name}{'victims'}{$victim}{'total'}) { $stats{$name}{'victims'}{$victim}{'total'} = 0; }
	    if(!$stats{$name}{'victims'}{$victim}{$weapon}) { $stats{$name}{'victims'}{$victim}{$weapon} = 0; }

	    
	    # If this was not a suicide, count it.
	    if($wasThisASuicide != 1)
	    {
		$stats{$name}{'total'}++;
		$stats{$victim}{'deaths'}++;
	    }
	    
	    # Increment each stats for this weapon
	    $stats{$name}{'weapons'}{$weapon}++;
	    $stats{$name}{'victims'}{$victim}{'total'}++;
	    $stats{$name}{'victims'}{$victim}{$weapon}++;

	    # Call the calc skill routine to keep track of this frag
	    &calcSkill($name, $victim, \%stats);

	    $wasThisASuicide = 0;
	}
    }
    return(\%stats);
}

sub createIPpage
{
    #L 10/15/1999 - 14:05:37: "KOSH<1><WON:4800179>" connected, address "206.172.191.172:27005"

    my $settings = $_[0];
    my $stats = $_[1];
    my $array = $_[2];
    my $ARGS = $_[3];

    my %ips = ();    
    my $line = ();
    my $connectPage = 0;
    my $thisrow = 0;

    my ($time, $name, $playerNum, $wonID, $ip, $port, $count, $num) = 0;
    my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst)=localtime(time);
    
    $year = $year + 1900;
    $mon = $mon + 1;

    my $monthStart = $mon - $settings->{'monthsToUse'};

    my ($cMon, $cDay, $cYear) = 0;

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

    while($line = shift @$array)
    {
	$line =~ /^L (.+?): \"(.+?)<(.+?)><WON:(.+?)>\" connected, address \"(.+?):(.+?)\"/;
	
	$time      = $1;
	$name      = $2;
	$playerNum = $3;
	$wonID     = $4;
	$ip        = $5;
	$port      = $6;
	
	$time =~ /^(.{1,2})\/(.{1,2})\/(....) \- (..):(..):(..)/;
	$cMon = $1;$cDay = $2;$cYear = $3;

	$lastNum = "$cYear$cMon$cDay";

	if(!$ips{$ip})                         { $ips{$ip}                         = (); }
	if(!$ips{$ip}{$name}{'count'})         { $ips{$ip}{$name}{'count'}         = 0;  }
	if(!$stats->{$name}{'totalConnects'})  { $stats->{$name}{'totalConnects'}  = 0;  }	
	if(!$ips{$ip}{$name}{'lastComp'})      { $ips{$ip}{$name}{'lastComp'}      = 0;  }
	if(!$ips{$ip}{$name}{'wonid'}{$wonID}) { $ips{$ip}{$name}{'wonid'}{$wonID} = 0;  }

	$ips{$ip}{$name}{'count'}++;
	$stats->{$name}{'totalConnects'}++;
	$ips{$ip}{$name}{'wonid'}{$wonID}++;

	if($ips{$ip}{$name}{'lastComp'} <= $lastNum)
	{
	    $ips{$ip}{$name}{'lastComp'} = "$cYear$cMon$cDay";
	    $ips{$ip}{$name}{'last'}     = "$time";
	    $stats->{$name}{'lastIP'}    = $ip;

	}
    }

    if($settings->{'pubConnectStats'} eq "1" || @$ARGS[0] ne "-file")
    {
	$connectPage = "./connect_stats.html";
    }
    else
    {
	$connectPage = "$ENV{'HOME'}/connect_stats.html";
    }

    open(FILE, ">$connectPage");

    print FILE "<html><head><title>Connection Statistics</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 "<br><br><center><table width='90%' border='1'>\n";
    print FILE "<tr><td><font size='+1'><b>IP:</b></font></td>\n";
    print FILE "<td><font size='+1'>[# of connects] <b>Name</b> (last on)</font></td></tr>\n";

    my $wonkey = 0;

    foreach $ip (sort { $ips{$b} <=> $ips{$a} } keys(%ips) )
    {
	unless(!$ip)
	{
	    print FILE "<tr><td><b>$ip</b></td><td align='left'>\n";
	    foreach $name ( keys %{$ips{$ip}} )
	    {
		print FILE "<table width='95%'><tr>\n";
		print FILE "<td align='left'>[ <font color='yellow'><b>$ips{$ip}{$name}{'count'}</b></font> ]</td>\n";
		print FILE "<td align='left'><b>$name</b></td>\n";
		print FILE "<td align='left'><b>(</b>$ips{$ip}{$name}{'last'}<b>)</b></td>\n";
		print FILE "<td align='right'><u>Won IDs</u><br>";

		foreach $wonkey (keys %{$ips{$ip}{$name}{'wonid'}})
		{
		    print FILE "$wonkey<br>\n";
		}
		print FILE "</td></tr></table>\n";
	    }
	    print FILE "</td></tr>\n";
	    $count++;
	}
    }

    print FILE "</table></center><br><br>\n";
    print FILE "<a href='$settings->{'relSkillFile'}'>Back to main listing</a><br></body></html>\n";
    close(FILE);
}

sub mergeLogs
{
    my $settings = $_[0];
    my $match = $_[1];
    my $ARGS = $_[2];

    my $file = 0;
    my $dir = 0;
    my @array = ();
    my $count = 0;

    my $month = 0;
    my $day = 0;
    my $year = 0;
    my $mo = 0;
    my $yr = 0;
    my $monthStart = 0;
    my $sizeTotals = 0;
    my $line = 0;

    if($settings->{'mode'} eq "now")
    {
	@time = localtime(time);
	
	$mo = $time[4] + 1;
	$yr = $time[5] + 1900;
	chomp($mo);chomp($yr);
	
	$monthStart = $mo - $settings->{'monthsToUse'};
    }
    elsif($settings->{'mode'} eq "prev")
    {
	$mo = @$ARGS[2];
	$yr = @$ARGS[3];
	$monthStart = @$ARGS[2];
    }

    my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,$atime,$mtime,$ctime,$blksize,$blocks)= ();

    opendir(DIR, "$settings->{'logDir'}");
    while($file = readdir DIR)
    {
        chomp($file);
        if($file =~ ".log")
        {
	    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
	     $atime,$mtime,$ctime,$blksize,$blocks)
		= stat("$settings->{'logDir'}/$file");

	    $sizeTotals+=$size;

            open(FILE, "$settings->{'logDir'}/$file");
            while($line = readline *FILE)
            {
		chomp($line);
		if($line !~ "<-1>")
		{
		    $line =~ /^.{2}(..)\/(..)\/(....)/;
		    $month = $1;
		    $day   = $2;
		    $year  = $3;
		    
		    if($month >= $monthStart && $month <= $mo && $year == $yr)
		    {
			if(($line =~ "killed" && $line =~ "with") && $match eq "logs")
			{
			    $array[$count] = $line;
			    $count++;
			}
			elsif($line =~ "connected, address" && $match eq "ips")
			{
			    $array[$count] = $line;
			    $count++;
			}
		    }
		}
	    }
            close(FILE);    
	    #if($settings->{'conserveCPU'} eq "yes") { sleep 1; }
	}
    }
    close(DIR);

    $settings->{'logSize'} = sprintf("%.2f MBytes", (($sizeTotals/1024)/1024));
    
    return(\@array);
}

sub parseConfig
{
    
    my $ARGS = $_[0];

    my $configFile = "halfStats.cfg";
    my @fileContents;
    my $variable = 0;
    my $value = 0;
    my %config = ();
    my $line = 0;
    my $firstChar = 0;
    my $rest = 0;
    my $key = 0;

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

    # save settings, forget comments and blank space
    foreach $line (@fileContents)
    {
	chomp($line);

	$firstChar = substr($line, 0, 1);

        if($firstChar ne "#" && $firstChar ne "")
        {
            ($variable, $value) = split(/\=/, $line, 2);
	    $config{$variable} = $value;
        }
        else
        {
            # do nothing, this is a comment
        }
    }

    # these are internal halfStats settings
    $config{'version'}    = "0.99b";
    $config{'killsFile'}  = "$config{'htmlDir'}/topten-highest_kills.html";
    $config{'deathsFile'} = "$config{'htmlDir'}/topten-highest_deaths.html";
    $config{'kpdFile'}    = "$config{'htmlDir'}/topten-highest_kpd.html";


    if(@$ARGS)
    {
	if(@$ARGS[0] eq "-file")
	{
	    $config{'skillFile'}  = "$config{'htmlDir'}/@$ARGS[1]/@$ARGS[3]/@$ARGS[2]/index.html";
	    $config{'relSkillFile'} = "@$ARGS[1]/@$ARGS[3]/@$ARGS[2]/index.html";
	    $config{'playerDir'} = "@$ARGS[1]/@$ARGS[3]/@$ARGS[2]/players";
	    $config{'mode'} = "prev";
	}
    }
    else
    {
	$config{'skillFile'}  = "$config{'htmlDir'}/index.html";
	$config{'relSkillFile'} = "index.html";
	$config{'playerDir'} = "players";
	$config{'mode'} = "now";
    }
    

    if($config{'OS'} ne "unix")
    {
	foreach $key (keys %config)
	{
	    if($key ne "serverBanner")
	    {
		$config{$key} =~ s/\//\\/g;
	    }
	}
    }

    return(\%config);
}

sub setKillsPerDeath
{
    my $stats = $_[0];
    my $key = 0;
    
    foreach $key (keys %{$stats})
    {
	if(!$stats->{$key}{'deaths'}){$stats->{$key}{'deaths'} = 0;}
	if(!$stats->{$key}{'total'}){$stats->{$key}{'total'} = 0;}

	if($stats->{$key}{'deaths'} > 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 $ARGS = $_[3];

    my $goodName = &removeJunk($player);

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

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

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


    open(PAGE, ">$file");
    if($settings->{'OS'} eq "unix"){flock(FILE, 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>\n";

    if($settings->{'pubConnectStats'} eq "1" || @$ARGS[0] ne "-file")
    {
	unless(!$stats->{$player}{'totalConnects'})
	{
	    print PAGE "<tr><td><br>This person has connected $stats->{$player}{'totalConnects'} times\n";
	    print PAGE "<b>[</b>Last ip: $stats->{$player}{'lastIP'}<b>]</b></td></tr></table>\n";
	}
    }

    print PAGE "<br><br><br>\n";
    print PAGE "<table width='75%' 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><br>\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><br>\n";
    print PAGE "$stats->{$player}{'deaths'}</center>\n";
    print PAGE "</font></td>\n";

    print PAGE "<td><font color='$bgc' face='helvetica'>\n";
    print PAGE "<center><i><b>Player Skill: </i></b><br>\n";
    print PAGE "$stats->{$player}{'skill'}</center>\n";
    print PAGE "</font></td>\n";

    if($settings->{'calcSuicides'} eq "yes")
    {
	if(!$stats->{$player}{'victims'}{$player}{'total'})
	{
	    $stats->{$player}{'victims'}{$player}{'total'} = 0;
	}
	print PAGE "<td><font color='$bgc' face='helvetica'>\n";
	print PAGE "<center><i><b>Suicide Total: </i></b><br>\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='99%' 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='99%' 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>$player\'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'})
	    {
		$stats->{$victim}{'victims'}{$player}{'total'} = 0;
	    }
	    if(!$stats->{$player}{'victims'}{$victim}{'total'})
	    {
		$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 = sprintf("%.2f", $stats->{$player}{'victims'}{$victim}{'total'});
	    }
	    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 align='left'><table width='75%' border='0'><tr>\n";
		    print PAGE "<td align='left'>$favCount</td>\n";
		    print PAGE "<td align='right'><img src='../images/$favWeap.gif' border='0' height='20' width='70'></td>\n";
		    print PAGE "</tr></table></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='../$settings->{'relSkillFile'}'>\n";
    print PAGE "<font size='+2'>Back to Main Player Listing</font>\n";
    print PAGE "</a></body></html>\n";
    if($settings->{'OS'} eq "unix"){flock(FILE, 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 writeTopTenPages
{
    my $stats = $_[0];
    my $settings = $_[1];
    my $file = $_[2];
    my $criteria = $_[3];

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

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

    
    open(FILE, ">$file");
    if($settings->{'OS'} eq "unix"){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 "<br><br><br>\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><a href='topten-highest_kills.html'>Total Kills</a></b></td>\n";
    print FILE "<td><b><a href='topten-highest_deaths.html'>Total Deaths</a></b></td>\n";
    print FILE "<td><b><a href='topten-highest_kpd.html'>Kills per Death</a></b></td>\n";
    print FILE "<td><b><a href='$settings->{'relSkillFile'}'>Skill rating</a></b></td>\n";
    print FILE "</tr>\n";

    foreach $name (sort {$stats->{$b}{$criteria} <=> $stats->{$a}{$criteria}} keys(%{$stats}))
    {
        if($stats->{$name}{'total'} && $name && $count <= 10)
        {
	    if($stats->{$name}{'total'} > $settings->{'minimumKills'})
	    {
		$goodName = &removeJunk($name);
		print FILE "<tr>\n";
		print FILE "<td><b>$count</b></td>\n";
		print FILE "<td><a href='$settings->{'playerDir'}/$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";
		$count++;
	    }
	}
    }
    print FILE "</table>\n";
    print FILE "</center></body></html>\n";
    if($settings->{'OS'} eq "unix"){flock(FILE, 8);}
}
		 
sub calcSkill
{
    my $killer = $_[0];
    my $victim = $_[1];
    my $stats = $_[2];
    my $killerSkill = 0;
    my $killeeSkill = 0;

    if(!$stats->{$victim}{'skill'} || $stats->{$victim}{'skill'} < 1000)
    { $stats->{$victim}{'skill'} = 1000; }

    if(!$stats->{$killer}{'skill'} || $stats->{$killer}{'skill'} < 1000)
    { $stats->{$killer}{'skill'} = 1000; }

    if($killer ne $victim)
    {
	$killerSkill = $stats->{$killer}{'skill'};
	$killeeSkill = $stats->{$victim}{'skill'};


	$stats->{$killer}{'skill'} = 
	    $killerSkill + (($killeeSkill / $killerSkill) * 10);
	
	if($killeeSkill < 2000)
	{
	    $stats->{$victim}{'skill'} = $stats->{$victim}{'skill'} - 10;
	}
	else
	{
	    $stats->{$victim}{'skill'} = $killeeSkill - (($killeeSkill / $killerSkill) * 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'});

}   

sub reportActivity
{
    use Socket;
    my $settings = $_[0];
    
    my $MasterHost     = "pimpstyle.iceburg.net";
    my $MasterPort     = "20808";
    my $DefaultTimeout = 120;

    my $url        = $settings->{'reportURL'};
    my $serverName = $settings->{'serverName'};
    my $ver        = $settings->{'version'};
    my $servIP     = $settings->{'ip_port'};
    my $mod        = $settings->{'mod'};
    my $admin      = $settings->{'admin'};
    my $email      = $settings->{'email'};

    my $pkt = "version=$ver;;url=$url;;name=$serverName;;ip_port=$servIP;;mod=$mod;;admin=$admin;;email=$email\n";

    # Create socket, use tcp
    my $tcpProto = getprotobyname('tcp') || 6;
    unless (socket(SOCKET, PF_INET, SOCK_STREAM, $tcpProto)) {
        print STDOUT "Socket error\n";
        return 0;
    }
    
      # Return if timeout
    $SIG{'ALRM'} = sub { close(SOCKET); print STDOUT "Timeout error: $!\n"; return 0; };
    
    # Connect to the server
    my $MasterAddr = inet_aton($MasterHost);
    my $PackedAddr = sockaddr_in($MasterPort, $MasterAddr);
    unless (connect(SOCKET, $PackedAddr)) {
        print STDOUT "  Connect error: $!\n";
        return 0;
    }
    
    # Send the data
    my $bytes = 0;
    my $length = length($pkt);
    unless ($bytes = send(SOCKET, $pkt, 0)) {
        print STDOUT "  Send error: $!\n";
        return 0;
    }
    close(SOCKET);
    return $bytes;
}


sub fixSkill
{

    my $stats = $_[0];

    my $key = 0;

    foreach $key (keys %{$stats})
    {
	if(!$stats->{$key}{'skill'})
	{
	    $stats->{$key}{'skill'} = 1000;
	}
    }

}
