#!/local/bin/perl

$armythresh = 3;

%short2let_Tmap = ("IND", "I", "FED", "F", "ROM", "R", "KLI", "K", "ORI", "O");
$teamcount = 0;

sub team_of {
    return substr($_[0], 0, 1);
}

sub set_pixel {
    local($x, $y, $val, $yoff, @img) = @_;

    if ($y+$yoff<0) {
	local(@_);
	$_[-$y-$yoff-1] = "";
	splice(@img, 0,0, @_);
	$yoff += @_;
    }
    local ($_) = $img[$y+$yoff];
    if (length() < $x+1) {
	$_ .= " "x($x+1-length());
    }
    substr($_, $x, 1) = $val;
    $img[$y+$yoff] = $_;
    return ($yoff, @img);
}

$spc_lasttime=-1;
$spc_lastt1=0;
$spc_lastt2=0;

sub set_planet_count {
    local($time, $t1, $t2) = @_;
    local($t);
    for ($t=$spc_lasttime+1; $t < $time; $t++) {
	@planetgraph = &set_pixel($t, -$spc_lastt1, "-", @planetgraph);
	@planetgraph = &set_pixel($t, $spc_lastt2, "-", @planetgraph);
    }
    $spc_lastt1 = $t1;
    $spc_lastt2 = $t2;
    @planetgraph = &set_pixel($time, -$t1, "+", @planetgraph);
    @planetgraph = &set_pixel($time, $t2, "+", @planetgraph);
    $spc_lasttime=$time;
}

$skc_lasttime=-1;
$skc_lastt1=0;
$skc_lastt2=0;

sub set_kill_count {
    local($time, $t1, $t2) = @_;
    local($t);
    for ($t=$skc_lasttime+1; $t < $time; $t++) {
	@killgraph = &set_pixel($t, -$skc_lastt1, "-", @killgraph);
	@killgraph = &set_pixel($t, $skc_lastt2, "-", @killgraph);
    }
    $skc_lastt1 = $t1;
    $skc_lastt2 = $t2;
    @killgraph = &set_pixel($time, -$t1, "+", @killgraph);
    @killgraph = &set_pixel($time, $t2, "+", @killgraph);
    $skc_lasttime=$time;
}

$scc_lasttime=-1;

sub set_carrier_count {
    local($time, $t1, $t2) = @_;
    local($t);
    for ($t=$scc_lasttime+1; $t < $time; $t++) {
	@carriergraph = &set_pixel($t, -$t1, "-", @carriergraph);
	@carriergraph = &set_pixel($t, $t2, "-", @carriergraph);
    }
    @carriergraph = &set_pixel($time, -$t1, "+", @carriergraph);
    @carriergraph = &set_pixel($time, $t2, "+", @carriergraph);
    $scc_lasttime=$time;
}

sub graph {
    local ($yoff, @graph) = @_;
    print "Count for ", $teamlets[0], " team\n";
    for ($i=0; $i<@graph; $i++) {
	local ($y)=$i-$yoff;
	local ($_) = $graph[$i];
	if (length() < $time+1) {
	    $_ .= " "x($time+1-length());
	}
	s/ /=/g if $y==0;
	for ($j=0; $j<=$time; $j+=10) {
	    if (substr($_, $j, 1)eq" ") {
		substr($_, $j, 1)="|";
	    }
	}
	if ($y%5==0 || $i==0 || $i==@graph-1 ) {
	    printf "%3d ", ($y<0 ? -$y : $y);
	    s/ /./g if $y%5==0;
	} else {
	    print " "x4;
	}
	print $_, "\n";
    }
    print "Count for ", $teamlets[1], " team\n";
}

sub update_death {
    local($v) = @_;

    $teamkills{&team_of($v)} -= $currentkills{$v};
    if ($currentkills{$v}) {
	$carriers{&team_of($v)}--;
	#print("$v is NOT a carrier\n");
    }

    $currentkills{$v} = 0;
}

#

sub player_name {
    local($_) = @_;
    s/[A-Z]{2}$//;
    s/^(.)./\1/;

	# rig stuff to count planets
    local($tlet) = $1;
    if ( ! defined($teamnum{$tlet}) ) {
	$teamlets[$teamcount] = $tlet;
	$teamnum{$tlet} = $teamcount++;
    }

    return $_;
}

sub enemies {
    local($p1, $p2) = @_;
    return ( substr($p1, 0, 1) ne substr($p2, 0, 1) );
}

sub parse_setplanet {
    local($name, $flags, $own, $armies) = @_;
    $planetcount{$short2let_Tmap{$own}} ++;
}

sub kill_credit {
    local ($victim, $doosh, $kills, $killer) = @_;
    
    return if ($killer eq "_");
    return if ($killer eq $victim);
    
    local ($v, $k);
    $v = &player_name($victim);
    $k = &player_name($killer);

    if (&enemies($v, $k)) {
	$E_DOOSH{$k} += $doosh;
	if (&in_base($killer)) { $E_BKILLS{$k} ++; }
	else { $E_KILLS{$k} ++;};
	# potential carriers killed?
	if ($kills>0.5) { $PC_KILLED{$k} ++; }
	if ($doosh) { $EC_KILLED{$k} ++; }

	if (!&in_base($killer)) {
	    #print "kill for $k\n";
	    if (!$currentkills{$k}) {
		$carriers{&team_of($k)}++;
		#print("$k is now a carrier\n");
	    }
	    $currentkills{$k}++;
	    $teamkills{&team_of($k)}++;
	}
    } else {
	$F_DOOSH{$k} += $doosh;
	$F_KILLS{$k} ++;
	if ($doosh) { $FC_KILLED{$k} ++; }
    }
}

sub in_base {
    local($_) = @_;
    return 0 unless /[A-Z]{2}$/;
    $_ = $&;
    return /(SB|WB|JS)/;
}

sub parse_kill {
    local($victim, $doosh, $alive, $kills, $killer1, $killer2) = @_;
    local($v, $k1, $k2);

    $v = &player_name($victim);
    $k1 = &player_name($killer1);
    $k2 = &player_name($killer2);

    $PLAYERS{$v} = 1;
    $PLAYERS{$k1} = 1;
    $PLAYERS{$k2} = 1;

    if (&in_base($victim)) {
	$BALIVE{$v} += $alive - $ALIVEADJ{$v};
	$BDEATHS{$v} ++;
	$C_ABKILLED{$v} += $doosh;
    } else {
	$ALIVE{$v} += $alive - $ALIVEADJ{$v};
	$DEATHS{$v} ++;
	$C_AKILLED{$v} += $doosh;
    }
    $ALIVEADJ{$v} = 0;

    &update_death($v);
    $deathcount{&team_of($v).$time}++;

    &kill_credit($victim, $doosh, $kills, $killer1);
    &kill_credit($victim, $doosh, $kills, $killer2);

    &set_kill_count($time, $teamkills{$teamlets[0]}, $teamkills{$teamlets[1]});
    &set_carrier_count($time, $carriers{$teamlets[0]},
		       $carriers{$teamlets[1]});
}

sub parse_plankill {
    local($victim, $doosh, $planet, $killer) = @_;
    local($v, $k);

    $v = &player_name($victim);
    $k = &player_name($killer);

    $PLAYERS{$v} = 1;
    $PLAYERS{$k} = 1;

    if (&in_base($victim)) {
	$BDEATHS{$v} ++;
	#$PDEATHS{$v} ++;
	$C_ABKILLED{$v} += $doosh;
    } else {
	$DEATHS{$v} ++;
	$PDEATHS{$v} ++;
	$C_AKILLED{$v} += $doosh;
    }
    $ALIVEADJ{$v} = 0;

    $deathcount[$time]++;

    &update_death($v);

    &kill_credit($victim, $doosh, $kills, $killer);

    &set_kill_count($time, $teamkills{$teamlets[0]}, $teamkills{$teamlets[1]});
    &set_carrier_count($time, $carriers{$teamlets[0]},
		       $carriers{$teamlets[1]});
}

sub parse_refit {
    local($player, $alive) = @_;
    local($plname);
    $plname = &player_name($player);

    $players{$plname} = 1;
    if (&in_base($player)) {
	$BALIVE{$plname} += $alive-$ALIVEADJ{$plname};
    } else {
	$ALIVE{$plname} += $alive-$ALIVEADJ{$plname};
    }
    $ALIVEADJ{$plname} = $alive;
}

sub parse_quit {
    local($player, $alive) = @_;
    local($plname);

    #print "parsing quit for $player, alive: $alive\n";
    $plname = &player_name($player);

    $players{$plname} = 1;
    if (&in_base($player)) {
	#print "old BALIVE ", $BALIVE{$plname};
	$BALIVE{$plname} += $alive-$ALIVEADJ{$plname};
	#print " new ", $BALIVE{$plname}, "\n";
    } else {
	$ALIVE{$plname} += $alive-$ALIVEADJ{$plname};

	&update_death($v);

	&set_kill_count($time, $teamkills{$teamlets[0]},
			$teamkills{$teamlets[1]});
	&set_carrier_count($time, $carriers{$teamlets[0]},
			   $carriers{$teamlets[1]});
    }
    $ALIVEADJ{$plname} = 0;
}

sub parse_pop {
    local($team, $armies) = @_;
    $POPS{$team} += $armies;
}

sub parse_pldest {
    local($plname, $player) = @_;
    #print "planet destroy by $player\n";
    $player = &player_name($player);
    $PL_DEST{$player} ++;

    warn "planet didn't match pattern" unless $plname =~ m/^$plan_pat$/;
    $planetcount{$short2let_Tmap{$3}}--;
    &set_planet_count($time, $planetcount{$teamlets[0]},
		      $planetcount{$teamlets[1]});
}

sub parse_pltake {
    local($plname, $player) = @_;
    $player = &player_name($player);
    $PL_TAKE{$player} ++;

    warn "planet $plname didn't match pattern" unless $plname =~ m/^$plan_pat$/;
    $planetcount{$short2let_Tmap{$3}}++;
    &set_planet_count($time, $planetcount{$teamlets[0]},
		      $planetcount{$teamlets[1]});
}

sub parse_plaban {
    local($plname, $player) = @_;
    $player = &player_name($player);
    $PL_TAKE{$player} --;

    warn "planet $plname didn't match pattern" unless $plname =~ m/^$plan_pat$/;
    $planetcount{$short2let_Tmap{$3}}--;
    &set_planet_count($time, $planetcount{$teamlets[0]},
		      $planetcount{$teamlets[1]});
}

sub parse_beamup {
    local($player, $planet, $armies) = @_;

    $player = &player_name($player);
    if ($armies<=$armythresh) {
	$ARMIES_RETREAT{$player} ++;
    }
    $ARMIES_CARRIED{$player} ++;
}

sub parse_beamdown {
    local($player, $planet_own, $armies) = @_;

    $player = &player_name($player);
    if ($armies<=$armythresh) {
	$ARMIES_DELIVERED{$player} ++;
    } elsif (substr($planet_own,0,1) != substr($player,0,1)) {
	$ARMIES_WASTED{$player} ++;
    } else { # armies ferried don't count
	$ARMIES_CARRIED{$player} --;
    }
}

sub parse_xferup {
    local($player, $base) = @_;

    $player = &player_name($player);
    $base = &player_name($base);

    $ARMIES_CARRIED{$player} ++;
    $ARMIES_DELIVERED{$base} ++;
}

sub parse_xferdown {
    local($player, $base) = @_;

    $player = &player_name($player);
    $base = &player_name($base);

    $ARMIES_CARRIED{$player} --;
    $ARMIES_CARRIED{$base} ++;
}

sub parse_bomb {
    local($planet, $killer, $narmies) = @_;

    $killer = &player_name($killer);

    $ABOMB{$killer} += $narmies;
}

sub parse_resbomb {
    local($planet, $resource, $killer) = @_;

    $killer = &player_name($killer);

    $RESBOMB{$killer} ++;
}

sub parse_revolt {
    local($plname) = @_;
    warn "planet $plname didn't match pattern" unless $plname =~ m/^$plan_pat$/;
    local($teamlet) = $short2let_Tmap{$3};
    $planetcount{$teamlet}--;
    &set_planet_count($time, $planetcount{$teamlets[0]},
		      $planetcount{$teamlets[1]});
    @planetgraph = &set_pixel($time, $teamnum{$teamlet}*2-1, "*", @planetgraph);
}

sub parse_resgrow { }

#
#
#

$plan_pat = "#(\\d+) \\[(.*)] (IND|FED|ROM|KLI|ORI)";
$play_pat = "([IFRKO][0-9a-z] <[^>]*> [\0A-Z]{2}|_)";

while (<>) {
    if (/Planet: (.+)  ([0-9a-f]+)  (IND|FED|ROM|KLI|ORI)  -- armies (\d+)/) {
	&parse_setplanet($1, $2, $3, $4);
    } elsif (s/^(\d+)\t//) {
	$time = $1;
	if (/^kill ${play_pat}\+(\d+)a,(\d+)t,([0-9.]+)k by ${play_pat}&${play_pat}$/o) {
	    &parse_kill($1, $2, $3, $4, $5, $6);
	} elsif (/^kill ${play_pat}\+(\d+)a by ${plan_pat}&${play_pat}$/o) {
	    &parse_plankill($1, $2, $4, $6);
	} elsif (/^refit $play_pat (\d+)t$/o) {
	    &parse_refit($1, $2);
	} elsif (/^quit ${play_pat}\+(\d+)a,(\d+)t,([0-9.]+)k$/o) {
	    &parse_quit($1, $3);
	} elsif (/^pl_destroy ($plan_pat) by $play_pat$/o) {
	    &parse_pldest($1, $5);
	} elsif (/^pl_take ($plan_pat) by $play_pat$/o) {
	    &parse_pltake($1, $5);
	} elsif (/^pl_aban ($plan_pat) by $play_pat$/o) {
	    &parse_plaban($1, $5);
	} elsif (/^beamup $play_pat from $plan_pat@(\d+)a$/o) {
	    &parse_beamup($1, $3, $5);
	} elsif (/^beamdown $play_pat to $plan_pat@(\d+)a$/o) {
	    &parse_beamdown($1, $4, $5);
	} elsif (/^xfer $play_pat from $play_pat$/o) {
	    &parse_xferup($1, $2);
	} elsif (/^xfer $play_pat to $play_pat$/o) {
	    &parse_xferdown($1, $2);
	} elsif (/^bomb $plan_pat by $play_pat \((\d+)a\)$/o) {
	    &parse_bomb($2, $4, $5);
	} elsif (/^resbomb $plan_pat \((.*)\) by $play_pat$/o) {
	    &parse_resbomb($2, $4, $5);
	} elsif (/^poparmies ${plan_pat} ([-+]\d+)a$/o) {
	    &parse_pop($3, $4);
	} elsif (/^resgrow $plan_pat \((.*)\)$/o) {
	    &parse_resgrow($2, $4);
	} elsif (/^revolt ($plan_pat$)/o) {
	    &parse_revolt($1);
	} else {
	    print STDERR "Unrecognized2 : $_";
	}
    } else {
	    print STDERR "Unrecognized1 : $_";
    }
}

$PLAYERS{'_'} = undef;
undef $PLAYERS{'_'};

@pnames = sort { $a cmp $b } (keys %PLAYERS);

#'
print<<EOF
epk	enemy players killed
eao	enemy armies ogged
eck	enemy carriers killed
pck	potential carriers killed
ab	armies bombed
pld	planets destroyed (reduced to 0 armies)
plt	planets taken
rsb	resources bombed
tac	total armies carried (doesn't count ones beamed to starbases
		or onto safe planets)
nad	net armies delivered (total delivered to enemy planets with
		<=$armythresh armies PLUS total delivered to friendly planets
		with <$armythresh armies MINUS those beamed up from a friendly
		planet with <$armythresh armies)

fpk	friendly players killed
fao	friendly armies ogged
fck	friendly carriers killed
cak	carried armies killed
def	deaths by enemy fire (includes planets)
dpf	deaths by planetary fire (includes stars and tractor kills)

EOF
;
#print
# "0123456789012345678901234567890123456789012345678901234567890123456789\n";

printf("%-25s epk eao eck pck ab  pld plt rsb tac nad pad\n", "player name");
foreach $player (@pnames) {
    local($nad) = ($ARMIES_DELIVERED{$player}-$ARMIES_RETREAT{$player});
    printf "%-25s %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n",
#'
	$player,
	$E_KILLS{$player}, $E_DOOSH{$player}, $EC_KILLED{$player},
	$PC_KILLED{$player}, $ABOMB{$player},
	$PL_DEST{$player}, $PL_TAKE{$player}, $RESBOMB{$player},
	$ARMIES_CARRIED{$player}, $nad,
	$ARMIES_CARRIED{$player} ? int(100*$nad/ $ARMIES_CARRIED{$player}) : 0;
}

printf("%-25s fpk fao fck cak def dpf | ratio min\n", "player name");
foreach $player (@pnames) {
    printf "%-25s %3d %3d %3d %3d %3d %3d | %5.1f %3d\n",
	$player,
	$F_KILLS{$player}, $F_DOOSH{$player}, $FC_KILLED{$player},
	$C_AKILLED{$player}, $DEATHS{$player}, $PDEATHS{$player},
	($DEATHS{$player}-$PDEATHS{$player}) ? ($E_KILLS{$player}/($DEATHS{$player}-$PDEATHS{$player})) : 100,
	$ALIVE{$player}/(60*10);
}

printf "%-25s min epk def\n", "";
foreach $player (@pnames) {
	next unless $BALIVE{$player}
		|| $E_BKILLS{$player}
		|| $BDEATHS{$player};
    printf "%-25s %3d %3d %3d\n",
	$player,
	$BALIVE{$player}/(60*10),
	$E_BKILLS{$player}, $BDEATHS{$player};
}

print "\n\n";

print "                        Planet graph\n";
&graph(@planetgraph);

print "\n\n";

print "                      Sum of kills graph\n";
&graph(@killgraph);

print "\n\n";

print "                    Potential carrier graph\n";
&graph(@carriergraph);

print "\n\n";

print "                         Death graph\n";
@_=();
for ($i=0; ;$i++) {
    local ($_, $done) = (" "x$time, 1);
    for ($j=0; $j<=$time; $j++) {
	if ($deathcount{$teamlets[0].$j}>$i) {
	    substr($_, $j, 1) = "#";
	    $done=0;
	}
    }
    last if $done;
    unshift(@_, $_);
}
push(@_, "+".("---------+"x($time/10)));
for ($i=0; ;$i++) {
    local ($_, $done) = (" "x$time, 1);
    for ($j=0; $j<=$time; $j++) {
	if ($deathcount{$teamlets[1].$j}>$i) {
	    substr($_, $j, 1) = "#";
	    $done=0;
	}
    }
    last if $done;
    push(@_, $_);
}
unshift(@_, "Count for ". $teamlets[0]. " team\n");
push(@_, "Count for ". $teamlets[1]. " team\n");


foreach (@_) {
    print "    ", $_, "\n";
}
