#!/usr/bin/perl
use LWP::Simple;
use HTML::Tree;
my $save_dir = "save";
my $bench_dir = "bench";
my $score_db = "score_db";
printf("Opening save directory: $save_dir\n");
opendir(DIR, $save_dir);
@BENCH = grep { !(/^\./) && -f "$save_dir/$_" } readdir(DIR);
close DIR;
$bench = @BENCH;
printf("Got %d entries from $save_dir\n", $bench);
my $hill_url = 'http://sal.math.ualberta.ca/hill.php?key=nano';
my $mypid = 45;
my $hill_card = get_score_card($hill_url);
my @HC = split(/\n/, $hill_card);
#find warriors we need scorecards for
foreach $hc (@HC){
my ($rank, $win, $loss, $tie, $wid, $name, $pid, $author, $pt, $pg, $age) = split(/\t/, $hc);
if($pid == $mypid && !($wid eq "")){
$name =~ s/-nano-eve78//;
$name =~ s/-eve78//;
foreach $W (@BENCH){
if($W eq $name){
print "Found match for warrior on score card $name\n";
$match = 1;
push(@WARRIORS, $W);
$SCURL{$W} = "http://sal.math.ualberta.ca/warrior.php?key=nano&id=$wid";
}
}
if($match != 1){
print("Couldn't find a match for $name in $save_dir");
next;
}
}
}
if(@WARRIORS > 0){
#process the score cards for warriors we found
foreach $W (@WARRIORS){
printf("Score card for $scurl\n");
$scards{$W} = get_score_card($SCURL{$W});
}
foreach $W (@WARRIORS){
print "Processing $W\n";
parse_scorecard($scards{$W}, \@HILL, \%HTAKEN, \%HGIVEN);
$HILL_TAKEN{$W} = \%HTAKEN;
$HILL_GIVEN{$W} = \%HGIVEN;
}
foreach $W (@WARRIORS){
print "Benchmarking $W\n";
bench_warrior($W, \@BENCH, \%BTAKEN, \%BGIVEN);
$BENCH_TAKEN{$W} = \%BTAKEN;
$BENCH_GIVEN{$W} = \%BGIVEN;
}
%seen = ();
@HILL = grep { ! $seen{$_} ++ } @HILL;
%seen = ();
@WARRIORS = grep { ! $seen{$_} ++ } @WARRIORS;
foreach $H (@HILL){
printf("Processing hill warrior $H\n");
$low = 999.9; #impossibly high low to start
$low_w = "";
foreach $B (@BENCH){
$total = 0;
foreach $W (@WARRIORS){
$a = abs($HILL_TAKEN{$W}{$H} - $BENCH_TAKEN{$W}{$B});
$b = abs($HILL_GIVEN{$W}{$H} - $BENCH_GIVEN{$W}{$B});
$total = $total + ($a * $a) + ($b * $b);
#print "$H -> $B -> $W ### $HILL_TAKEN{$W}{$H} - $BENCH_TAKEN{$W}{$B} + $HILL_GIVEN{$W}{$H} - $BENCH_GIVEN{$W}{$B} ERROR: $total \n";
}
$total = sqrt($total);
if($total < $low){
$low = $total;
$low_w = $B;
}
}
printf("Selected %s with error %3.2f to emulate %s\n", $low_w, $low, $H);
foreach $W (@WARRIORS){
printf("%10s -> %10s\t\tTaken: %3.1f\tGiven: %3.1f\n", $W, $H, $HILL_TAKEN{$W}{$H}, $HILL_GIVEN{$W}{$H});
printf("%10s -> %10s\t\tTaken: %3.1f\tGiven: %3.1f\n", $W, $H, $BENCH_TAKEN{$W}{$low_w}, $BENCH_GIVEN{$W}{$low_w});
}
system("cp $save_dir/$low_w $bench_dir");
}
} else {
# we had nothing on the hill, might as well make a random benchmark
system("./mkrandbench.pl");
}
sub parse_scorecard{
my ($score_card, $WARRIORS, $PTAKEN, $PGIVEN) = @_;
@C = split(/\n/, $score_card);
foreach $c (@C){
chomp $c;
my ($rank, $win, $loss, $tie, $wid, $name, $pid, $author, $pt, $pg, $age) = split(/\t/, $c);
$name = trim($name);
$name =~ s/://;
$pt = trim($pt);
$pg = trim($pg);
printf("%s:%s:%s:%s:%3.2f:%3.2f\n", $wid, $name, $pid, $author, $pt, $pg);
push(@$WARRIORS, $wid);
$$WNAMES{$wid} = $name;
$$PTAKEN{$wid} = $pt;
$$PGIVEN{$wid} = $pg;
}
close C;
}
sub get_score_card {
my $url = shift;
my $skipped_header = 0;
my $raw_score_card = get($url) || print "Failed to retrieve $url!\n";
$raw_score_card =~ s/ //g;
my $root = HTML::TreeBuilder->new;
$root->parse($raw_score_card);
$root->eof();
# debugging $root->dump;
my $score_card;
foreach $table ($root->find_by_tag_name( 'table' )){
foreach $tr ($table->find_by_tag_name( 'tr' )){
if($tr->as_text() =~ /%L/){
$skipped_header = 1;
next;
}
if($skipped_header != 1){
next;
}
foreach $td ($tr->find_by_tag_name( 'td' )){
$tab_text = $td->as_HTML();
if($tab_text =~ /href/){
#this is a player or warrior name link
if($tab_text =~ /player=/){
$tab_text =~ /player=([0-9]+)/;
$id = $1;
} else {
$tab_text =~ /id=([0-9]+)&/;
$id = $1;
}
$name = $td->as_text();
$tab_text = "$id\t$name";
} else {
$tab_text = $td->as_text();
}
$score_card = "$score_card$tab_text\t";
}
$score_card = "$score_card\n";
}
last;
}
return $score_card;
}
#Trim leading and trailing whitespace, from orielly.
sub trim {
my $out = shift;
$out =~ s/^\s+//;
$out =~ s/\s+$//;
return $out;
}
sub check_cache($name, $bench){
my ($name, $bench) = @_;
open(FH,"$score_db/$name/$bench") || return "None";
while(){
chomp;
($taken, $given) = split(/:/);
}
close(FH);
return [$taken, $given];
}
sub write_cache($name, $bench, $taken, $given){
my ($name, $bench, $taken, $given) = @_;
opendir(FH, "$score_db/$name") || mkdir "$score_db/$name";
close(FH);
open(FH,">$score_db/$name/$bench");
print FH "$taken:$given\n";
close(FH);
}
sub bench_warrior( $name, \@BENCH, \%PTAKEN, \%PGIVEN){
my ($name, $BENCH, $PTAKEN, $PGIVEN) = @_;
for(my $j = 0; $j < @$BENCH; $j++){
my $first = 0;
my $cache = &check_cache($name, $BENCH[$j]);
if($cache eq "None"){
$cache = &check_cache($BENCH[$j], $name);
if(!($cache eq "None")){
($bwin, $owin) = @{$cache};
$cache = [$owin, $bwin];
}
}
if($cache eq "None"){
open(PMARS,"./pmars -s 80 -c 800 -p 80 -d 5 -l 5 -P -b -k $save_dir/$name $save_dir/$$BENCH[$j]|");
while () {
#Get scores
chomp;
my($Wins, $Ties) = split;
if($first == 0){
$owin = $Wins;
$otie = $Ties;
$owin = ($owin * 3) + $otie;
$first++;
} else {
$bwin = $Wins;
$btie = $Ties;
$bwin = ($bwin * 3) + $btie;
last;
}
}
&write_cache($name, $BENCH[$j], $owin, $bwin);
} else {
($owin, $bwin) = @{$cache};
}
$$PTAKEN{$$BENCH[$j]} = (($bwin) * 300) / 426;
$$PGIVEN{$$BENCH[$j]} = (($owin) * 300) / 426;
#print "$$BENCH[$j] $$PTAKEN{$$BENCH[$j]} $$PGIVEN{$$BENCH[$j]}\n";
close(PMARS);
}
}