#!/usr/bin/perl

$usage = "$0 <first stats file> <second stats file> [number of iterations]\n";
$set1 = shift @ARGV or die $usage;
$set2 = shift @ARGV or die $usage;
$ITER = shift @ARGV;

#$ITER = 104857600;
#$ITER = 1048576;
#$ITER = 104857;
$ITER = 10485 if $ITER eq "";
#$ITER = 1048;
#$ITER = 104;

@firsttotals;
@first;
@secondtotals;
@second;
@sametotals;

open(FIRST, "<$set1") or die "Couldn't open $set1 for reading:$!\n";
while(<FIRST>)
{
	chomp;
	my $line = $_;
	my @fields = split;
	for(my $i = 1; $i <= $#fields; $i++)
	{
		$firsttotals[$i] += $fields[$i];
	}
	push @fields, $line;
	push @first, [ @fields ];
}
close FIRST;



open(SECOND, "<$set2") or die "Couldn't open $set2 for reading:$!\n";
while(<SECOND>)
{
	chomp;
	my $line = $_;
	my @fields = split;
	for(my $i = 1; $i <= $#fields; $i++)
	{
		$secondtotals[$i] += $fields[$i];
	}
	push @fields, $line;
	push @second, [ @fields ];


	if($second[$#second]->[$#fields] eq $first[$#second]->[$#fields])
	{#results are the same for both sets, don't bother shuffling, just count
		for(my $i = 1; $i < $#fields; $i++)
		{
			$sametotals[$i] += $fields[$i];
		}
	}
	else
	{
		push @firstdiff, $first[$#second];
		push @seconddiff, $second[$#second];
	}
}
close SECOND;

# filename, correctall, goldtotal, testtotal, correctargs, goldargs, testargs,
# correctnames, goldnames, testnames, correctnargs, goldnargs, testnargs

$firstprecisionall = 0;
$firstrecallall = 0;
$firstfscoreall = 0;
$firstprecisionall = $firsttotals[1]/$firsttotals[3] if $firsttotals[3] > 0;
$firstrecallall = $firsttotals[1]/$firsttotals[2] if $firsttotals[2] > 0;
$firstfscoreall =
	2*$firstprecisionall*$firstrecallall/($firstprecisionall+$firstrecallall) 
	if ($firstprecisionall+$firstrecallall) > 0;
$secondprecisionall = 0;
$secondrecallall = 0;
$secondfscoreall = 0;
$secondprecisionall = $secondtotals[1]/$secondtotals[3] if $secondtotals[3] > 0;
$secondrecallall = $secondtotals[1]/$secondtotals[2] if $secondtotals[2] > 0;
$secondfscoreall =
	2*$secondprecisionall*$secondrecallall/($secondprecisionall+$secondrecallall)
	if ($secondprecisionall+$secondrecallall) > 0;

$firstprecisionargs = 0;
$firstrecallargs = 0;
$firstfscoreargs = 0;
$firstprecisionargs = $firsttotals[4]/$firsttotals[6] if $firsttotals[6] > 0;
$firstrecallargs = $firsttotals[4]/$firsttotals[5] if $firsttotals[5] > 0;
$firstfscoreargs =
2*$firstprecisionargs*$firstrecallargs/($firstprecisionargs+$firstrecallargs) 
	if ($firstprecisionargs+$firstrecallargs) > 0;
$secondprecisionargs = 0;
$secondrecallargs = 0;
$secondfscoreargs = 0;
$secondprecisionargs = $secondtotals[4]/$secondtotals[6] if $secondtotals[6] > 0;
$secondrecallargs = $secondtotals[4]/$secondtotals[5] if $secondtotals[5] > 0;
$secondfscoreargs =
2*$secondprecisionargs*$secondrecallargs/($secondprecisionargs+$secondrecallargs)
	if ($secondprecisionargs+$secondrecallargs) > 0;

$firstprecisionnames = 0;
$firstrecallnames = 0;
$firstfscorenames = 0;
$firstprecisionnames = $firsttotals[7]/$firsttotals[9] if $firsttotals[9] > 0;
$firstrecallnames = $firsttotals[7]/$firsttotals[8] if $firsttotals[8] > 0;
$firstfscorenames =
2*$firstprecisionnames*$firstrecallnames/($firstprecisionnames+$firstrecallnames) 
	if ($firstprecisionnames+$firstrecallnames) > 0;
$secondprecisionnames = 0;
$secondrecallnames = 0;
$secondfscorenames = 0;
$secondprecisionnames = $secondtotals[7]/$secondtotals[9] if $secondtotals[9] > 0;
$secondrecallnames = $secondtotals[7]/$secondtotals[8] if $secondtotals[8] > 0;
$secondfscorenames =
2*$secondprecisionnames*$secondrecallnames/($secondprecisionnames+$secondrecallnames)
	if ($secondprecisionnames+$secondrecallnames) > 0;

$firstprecisionnargs = 0;
$firstrecallnargs = 0;
$firstfscorenargs = 0;
$firstprecisionnargs = $firsttotals[10]/$firsttotals[12] if $firsttotals[12] > 0;
$firstrecallnargs = $firsttotals[10]/$firsttotals[11] if $firsttotals[11] > 0;
$firstfscorenargs =
2*$firstprecisionnargs*$firstrecallnargs/($firstprecisionnargs+$firstrecallnargs) 
	if ($firstprecisionnargs+$firstrecallnargs) > 0;
$secondprecisionnargs = 0;
$secondrecallnargs = 0;
$secondfscorenargs = 0;
$secondprecisionnargs = $secondtotals[10]/$secondtotals[12] if $secondtotals[12] > 0;
$secondrecallnargs = $secondtotals[10]/$secondtotals[11] if $secondtotals[11] > 0;
$secondfscorenargs =
2*$secondprecisionnargs*$secondrecallnargs/($secondprecisionnargs+$secondrecallnargs)
	if ($secondprecisionnargs+$secondrecallnargs) > 0;

$origprecalldiff = $firstprecisionall - $secondprecisionall;
$precallfactor = $origprecalldiff<0?-1:1;
$origrecallalldiff = $firstrecallall - $secondrecallall;
$recallallfactor = $origrecallalldiff<0?-1:1;
$origfscorealldiff = $firstfscoreall - $secondfscoreall;
$fscoreallfactor = $origfscorealldiff<0?-1:1;
$origprecargsdiff = $firstprecisionargs - $secondprecisionargs;
$precargsfactor = $origprecargsdiff<0?-1:1;
$origrecalnargsdiff = $firstrecalnargs - $secondrecalnargs;
$recalnargsfactor = $origrecalnargsdiff<0?-1:1;
$origfscoreargsdiff = $firstfscoreargs - $secondfscoreargs;
$fscoreargsfactor = $origfscoreargsdiff<0?-1:1;
$origprecnamesdiff = $firstprecisionnames - $secondprecisionnames;
$precnamesfactor = $origprecnamesdiff<0?-1:1;
$origrecallnamesdiff = $firstrecallnames - $secondrecallnames;
$recallnamesfactor = $origrecallnamesdiff<0?-1:1;
$origfscorenamesdiff = $firstfscorenames - $secondfscorenames;
$fscorenamesfactor = $origfscorenamesdiff<0?-1:1;
$origprecnargsdiff = $firstprecisionnargs - $secondprecisionnargs;
$precnargsfactor = $origprecnargsdiff<0?-1:1;
$origrecallnargsdiff = $firstrecallnargs - $secondrecallnargs;
$recallnargsfactor = $origrecallnargsdiff<0?-1:1;
$origfscorenargsdiff = $firstfscorenargs - $secondfscorenargs;
$fscorenargsfactor = $origfscorenargsdiff<0?-1:1;

srand(time() ^ ($$ + ($$ << 15)) );

$criteria = 0;
for $iter (1..$ITER)
{
	if ($iter > 1 && $iter % 1000 == 1) 
	{
		print STDERR "Completed ", ($iter - 1), " iterations\n";
	}

	my @tot1;
	my @tot2;
	for(my $x=1; $x <= $#sametotals; $x++)
	{
		$tot1[$x] = $sametotals[$x];
		$tot2[$x] = $sametotals[$x];
	}
	for $i (0 .. $#firstdiff)
	{
		$shuffle = rand;
		if($shuffle > 0.5)
		{#swap
			for(my $x=1; $x <= $#tot1; $x++)
			{
				$tot1[$x] += $seconddiff[$i]->[$x];
				$tot2[$x] += $firstdiff[$i]->[$x];
			}
		}
		else
		{
			for(my $x=1; $x <= $#tot1; $x++)
			{
				$tot1[$x] += $firstdiff[$i]->[$x];
				$tot2[$x] += $seconddiff[$i]->[$x];
			}
		}
	}

	$p1all = 0;
	$p1all = $tot1[1]/$tot1[3] if $tot1[3] > 0;
	$p2all = 0;
	$p2all = $tot2[1]/$tot2[3] if $tot2[3] > 0;
	$palldiff = $p1all - $p2all;
	$pallcriteria++ 
		if($palldiff*$precallfactor > $origprecalldiff*$precallfactor);

	$r1all = 0;
	$r1all = $tot1[1]/$tot1[2] if $tot1[2] > 0;
	$r2all = 0;
	$r2all = $tot2[1]/$tot2[2] if $tot2[2] > 0;
	$ralldiff = $r1all - $r2all;
	$rallcriteria++ 
		if($ralldiff*$recallallfactor > $origrecallalldiff*$recallallfactor);

	$f1all = 0;
	$f1all = 2*$p1all*$r1all/($p1all+$r1all) if ($p1all+$r1all) > 0;
	$f2all = 0;
	$f2all = 2*$p2all*$r2all/($p2all+$r2all) if ($p2all+$r2all) > 0;
	$falldiff = $f1all - $f2all;
	$fallcriteria++ 
		if($falldiff*$fscoreallfactor > $origfscorealldiff*$fscoreallfactor);

	$p1args = 0;
	$p1args = $tot1[4]/$tot1[6] if $tot1[6] > 0;
	$p2args = 0;
	$p2args = $tot2[4]/$tot2[6] if $tot2[6] > 0;
	$pargsdiff = $p1args - $p2args;
	$pargscriteria++ 
		if($pargsdiff*$precargsfactor > $origprecargsdiff*$precargsfactor);

	$r1args = 0;
	$r1args = $tot1[4]/$tot1[5] if $tot1[5] > 0;
	$r2args = 0;
	$r2args = $tot2[4]/$tot2[5] if $tot2[5] > 0;
	$rargsdiff = $r1args - $r2args;
	$rargscriteria++ 
		if($rargsdiff*$recallargsfactor > $origrecallargsdiff*$recallargsfactor);

	$f1args = 0;
	$f1args = 2*$p1args*$r1args/($p1args+$r1args) if ($p1args+$r1args) > 0;
	$f2args = 0;
	$f2args = 2*$p2args*$r2args/($p2args+$r2args) if ($p2args+$r2args) > 0;
	$fargsdiff = $f1args - $f2args;
	$fargscriteria++ 
		if($fargsdiff*$fscoreargsfactor > $origfscoreargsdiff*$fscoreargsfactor);

	$p1names = 0;
	$p1names = $tot1[7]/$tot1[9] if $tot1[9] > 0;
	$p2names = 0;
	$p2names = $tot2[7]/$tot2[9] if $tot2[9] > 0;
	$pnamesdiff = $p1names - $p2names;
	$pnamescriteria++ 
		if($pnamesdiff*$precnamesfactor > $origprecnamesdiff*$precnamesfactor);

	$r1names = 0;
	$r1names = $tot1[7]/$tot1[8] if $tot1[8] > 0;
	$r2names = 0;
	$r2names = $tot2[7]/$tot2[8] if $tot2[8] > 0;
	$rnamesdiff = $r1names - $r2names;
	$rnamescriteria++ 
	if($rnamesdiff*$recallnamesfactor>$origrecallnamesdiff*$recallnamesfactor);

	$f1names = 0;
	$f1names = 2*$p1names*$r1names/($p1names+$r1names) if ($p1names+$r1names)>0;
	$f2names = 0;
	$f2names = 2*$p2names*$r2names/($p2names+$r2names) if ($p2names+$r2names)>0;
	$fnamesdiff = $f1names - $f2names;
	$fnamescriteria++ 
	if($fnamesdiff*$fscorenamesfactor>$origfscorenamesdiff*$fscorenamesfactor);

	$p1nargs = 0;
	$p1nargs = $tot1[10]/$tot1[12] if $tot1[12] > 0;
	$p2nargs = 0;
	$p2nargs = $tot2[10]/$tot2[12] if $tot2[12] > 0;
	$pnargsdiff = $p1nargs - $p2nargs;
	$pnargscriteria++ 
		if($pnargsdiff*$precnargsfactor > $origprecnargsdiff*$precnargsfactor);

	$r1nargs = 0;
	$r1nargs = $tot1[10]/$tot1[11] if $tot1[11] > 0;
	$r2nargs = 0;
	$r2nargs = $tot2[10]/$tot2[11] if $tot2[11] > 0;
	$rnargsdiff = $r1nargs - $r2nargs;
	$rnargscriteria++ 
		if($rnargsdiff*$recallnargsfactor >
		$origrecallnargsdiff*$recallnargsfactor);

	$f1nargs = 0;
	$f1nargs = 2*$p1nargs*$r1nargs/($p1nargs+$r1nargs) if ($p1nargs+$r1nargs)>0;
	$f2nargs = 0;
	$f2nargs = 2*$p2nargs*$r2nargs/($p2nargs+$r2nargs) if ($p2nargs+$r2nargs)>0;
	$fnargsdiff = $f1nargs - $f2nargs;
	$fnargscriteria++ 
		if($fnargsdiff*$fscorenargsfactor >
		$origfscorenargsdiff*$fscorenargsfactor);
}

printf "after $ITER iterations: (%d differences)\n", $#firstdiff;

print "\nEDM\n";
printf "precisions: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstprecisionall, $secondprecisionall, ($pallcriteria+1)/($ITER+1);
printf "   recalls: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstrecallall, $secondrecallall, ($rallcriteria+1)/($ITER+1);
printf "   fscores: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstfscoreall, $secondfscoreall, ($fallcriteria+1)/($ITER+1);

print "\nEDM_NA\n";
printf "precisions: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstprecisionlargs, $secondprecisionlargs, ($plargscriteria+1)/($ITER+1);
printf "   recalls: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstrecalllargs, $secondrecalllargs, ($rlargscriteria+1)/($ITER+1);
printf "   fscores: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstfscorelargs, $secondfscorelargs, ($flargscriteria+1)/($ITER+1);
		
print "\nEDM_A\n";
printf "precisions: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstprecisionargs, $secondprecisionargs, ($pargscriteria+1)/($ITER+1);
printf "   recalls: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstrecallargs, $secondrecallargs, ($rargscriteria+1)/($ITER+1);
printf "   fscores: %.4f and %.4f. Probability of null hypothesis is %.6f\n",
	$firstfscoreargs, $secondfscoreargs, ($fargscriteria+1)/($ITER+1);
