#!perl
#
#
# Prepare a relatively detailed report on the state of the computation..
#
# Modification history:
# 24 Aug 2005  TA  Written

use strict;
use warnings;
use Lingua::EN::Numbers qw(num2en num2en_ordinal);
use File::Slurp;
use File::Path;
use File::Copy;
use File::Temp;
use Data::Dumper;
use Getopt::Long;
use Cwd;

require './bin/tightknot_common.pl';

my @rounds = qw(stpaul overlook bogart bravado ipad galactica caprica);

my @PNAS = ("3_1_#_9_46", "3_1_#_9_15", "3_1_#_8_11_m", "3_1_#_8_15", 
"3_1_#_9_38_m",  "3_1_m_#_8_1_m",  "4_1_#_8_11",  "3_1_#_9_22_m",  
"4_1_#_8_1_m",  "3_1_m_#_9_2_m",  "3_1_m_#_8_15",  "3_1_m_#_9_22_m",  
"3_1_#_8_11",  "3_1_#_9_2",  "4_1_#_8_15_m",  "3_1_m_#_9_2",  
"3_1_#_8_15_m",  "4_1_#_8_11_m",  "3_1_m_#_9_46_m",  "3_1_m_#_9_38",  
"3_1_#_9_22",  "6_2_#_6_2_m",  "3_1_m_#_9_8_m",  "3_1_m_#_8_1",  
"3_1_m_#_9_46",  "3_1_#_9_38",  "3_1_m_#_8_15_m",  "6_2_#_6_2",  
"3_1_m_#_9_38_m",  "5_1_#_5_2_m",  "5_1_#_5_2",  "4_1_#_8_15",  
"3_1_#_9_46_m",  "3_1_#_8_1_m",  "3_1_#_8_1",  "3_1_#_9_17_m",  
"5_1_m_#_5_2", "3_1_m_#_9_43", "3_1_#_9_44", "4_1_#_8_21");

my $averagercond;

sub make_safekey {

    my $key = $_[0];
    my $safekey;
    my $texkey;

    my $cr;
    my $ind;
    my $comp;

    my $safeone;
    my $safetwo;
    my $safethree;
    
    if ( $key !~ /.vect/ ) {  #this is a knot type
	
	if ( $key =~ /(\d+)_(\d+)_(\d+)/ ) { # a link
	    
	    $safeone = $1; $safetwo = $2; $safethree = $3;

	    $cr = num2en($safeone); $comp = num2en($safetwo); $ind = num2en($safethree);
	    $cr =~ s/\s/\-/g; $comp =~ s/\s/\-/g; $ind =~ s/\s/\-/g;

	    $safekey = $cr.$comp.$ind;
	    $safekey =~ s/-//g;
	    $texkey = $safeone."^{".$safetwo."}_{".$safethree."}";

	    $cr = $safeone; $comp = $safetwo; $ind = $safethree;
	    
	} elsif ( $key =~ /(\d+)_(\d+)/ ) { # a knot
	
	    $safeone = $1; 
	    $safetwo = $2;
	    
	    $texkey = $safeone."_{".$safetwo."}";
    
	    $cr = num2en($safeone); $ind = num2en($safetwo);
	    $cr =~ s/\s/\-/g; $ind =~ s/\s/\-/g;

	    $safekey = $cr.$ind;
	    $safekey =~ s/-//g;
	
	    $cr = $safeone; $comp = 1; $ind = $safetwo;

	} else {

	    print "FAILED to match key ".$key."\n";

	}


    }
	
    my @retstuff = ($safekey,$texkey,$cr,$comp,$ind);

    return @retstuff;
	    
}

sub perltable {

    # We expect input in the following form

    # perltable(FILE,[40 50 50 50],["10.1 & 12", "14.1 & 11", "12.1 & 2"],"Temperature & Number of Fish","Water Temperature and Number of Fish Caught");

    my $fname=$_[0];
    my @rows=@{$_[1]};
    my @data=@{$_[2]};
    my $colheads=$_[3];
    my $caption=$_[4];
    my $maxcols=$_[5];
    my $label=$_[6];

    my $tab = 0;
    my $tabdatastart = 0;  #The first piece of data in this table.

    open(TABLE,">$fname") or die("Couldn't open $fname:$_\n");
    print "Called perltable with ".scalar @rows." tables of rows and ".scalar @data." data\n";

    foreach $tab (0..scalar @rows) {

	print "Survived to table $tab.\n";

	if (!defined($data[$tabdatastart])) { return; }

	my $cols =  int( scalar @data/$rows[$tab] + 1); 
	if ($cols > $maxcols) { $cols = $maxcols; }
	my $onetab = scalar @data/($maxcols*$rows[0]) < 1;

        # Number of entries / $rows on this table entries per col.

	print "Making Perl Table $tab of $rows[$tab] x $cols entries of ".scalar @data." total pieces of data.\n";
	my $colsperentry = ($colheads =~ tr/&//) + 1;
	print "Counting $colsperentry columns per item in data.\n";

	if (scalar @data - $tabdatastart < $rows[$tab]*$cols) { # We're on the last table

	    $rows[$tab] = int( (scalar @data - $tabdatastart + $cols-1)/$cols) + 1;
	    if ($rows[$tab] > 1) { $rows[$tab]--; } 

	    print "Balancing last table by resetting rows to $rows[$tab].\n";

	}

	print TABLE '\begin{table}[h]'."\n";
	print TABLE '\caption{\label{'.$label.num2en($tab+1).'}';
	if (!$onetab) { print TABLE 'Table '.($tab+1).' of '; }
	print TABLE $caption.'}'."\n";

	foreach my $j (0..$cols-1) {

	    if (defined $data[$tabdatastart + $j*$rows[$tab]]) {

		print TABLE '\begin{tabular}[t]{'.("l" x ($colsperentry)).'} \toprule'."\n";
		print TABLE $colheads."\\\\ \\midrule \n";

		foreach my $i (0..$rows[$tab]) {

		    my $ind = $tabdatastart + $i + $j*$rows[$tab];

		    if (defined $data[$ind]) {

			print TABLE "$data[$ind]";
			
		    } 

		}

		print TABLE '\bottomrule'."\n".'\end{tabular}'."\n";
		print TABLE '\hspace{0.25in}'."\n";

	    }

	}
	
	print TABLE '\end{table}'."\n";

	# We now update $tabdatastart;

	$tabdatastart += $rows[$tab]*$cols;

    }

    $|++;
    close(TABLE);

}

my $cwd;
$cwd = getcwd;
#open(DB,'KnotDB.pl');
my $DBFILE = read_file("${cwd}/knotdb/KnotDB.pl");
my %knots;

eval($DBFILE);

#close(DB);

my $okknots;
$okknots = 0;

my $okcomposites;
$okcomposites = 0;

my $totalcomposites;
$totalcomposites = 0;

my $totalknots;
$totalknots = 0;

my $key;

my $noComposites= '';
my $massMangle= '';
my $pushComposites = '';

GetOptions ( 'nocomposites|noComposites' => \$noComposites, 'massmangle|massMangle' => \$massMangle, 'pushComposites|pushcomposites' => \$pushComposites);

if ($noComposites) {

  print "Called with noComposites; removing composites from DB.\n";

  foreach $key ( keys %knots ) {

    if (defined($knots{$key}{summands})) {

      delete $knots{$key};

    }

  }

}

print "Checking database for potential knot okness.\n";

foreach $key ( keys %knots ) {

    if ($key =~ m/vect/) {

      $totalknots++;

      if (defined($knots{$key}{summands})) {

	$totalcomposites++;

      } 

      if ($knots{$key}{residual} < 0.01 && $knots{$key}{upperbound}/$knots{$key}{edges} < 1/8.0) {
	
	push @ { $knots{$knots{$key}{knot_type}}{okfiles} }, $key;
	$okknots++;
	#print "Found an acceptable $knots{$key}{knot_type}.\n";

	if (defined($knots{$key}{summands})) {

	  $okcomposites++;

	}
	
      }

    }

}

print "We have $okknots acceptable knots of $totalknots, including $okcomposites of $totalcomposites composite knots.\n";
print "The current round is ".$rounds[-1].", containing ";

my @thisround;
my @lastround;
my @lastcomp;

@thisround = grep(/$rounds[-1]/,keys %knots);
@lastround = grep(/$rounds[-2]/,keys %knots);

print scalar @thisround." files entered so far. \nSearching for corresponding files from round ".$rounds[-2]." which has ".scalar @lastround." files.\n";

my $lr;
my $tr;

foreach $tr (@thisround) {

  $lr = $tr;
  $lr =~ s/$rounds[-1]/$rounds[-2]/g;

  if (grep($lr,@lastround) > 0) {

    push(@lastcomp,$lr);

  }

}

print "Found ".scalar @lastcomp." files with matching knot types from ".$rounds[-2]."\n";
  
my $this_total_rop = 0;
my $this_total_res = 0;
my $last_total_rop = 0;
my $last_total_res = 0;

foreach (@lastcomp) {

  $lr = $_;
  $lr =~ s/$rounds[-2]/$rounds[-1]/g;

  $this_total_rop += $knots{$lr}{upperbound};
  $last_total_rop += $knots{$_}{upperbound};

  $this_total_res += $knots{$lr}{residual};
  $last_total_res += $knots{$_}{residual};

}

print "Total ropelength/residual of files in round $rounds[-1]: $this_total_rop/$this_total_res. \n";
print "Total ropelength/residual of matching $rounds[-2] files: $last_total_rop/$last_total_res. \n";
print "------------------------\n";


my $numkeys = keys ( %knots );
print "We have $numkeys entries in the original database. Looking for knots.\n";

# first, a pass to remove files from the hash

foreach $key ( sort(keys %knots) ) {

    if ($key =~ /.vect/) {

	delete $knots{$key};

    }

}

$numkeys = keys ( %knots );
print "There seem to be $numkeys knots and links in the database. Generating TeX macros and data...\n";
print "We have $okknots acceptable (resolution > 8, residual < 0.01) finished runs\n";

my $safekey;
my $texkey;
my $cr;
my $comp;
my $ind;

foreach $key ( sort(keys %knots) ) {

  $texkey = $knots{$key}{tex};
  $cr = $knots{$key}{cr};
  $comp =   $knots{$key}{comp};
  $ind =  $knots{$key}{index};

    # Now some formatting modifications for the table.
  
  $knots{$key}{ropelength} = sprintf("%2.4f",$knots{$key}{ropelength});
  $knots{$key}{upperbound} = sprintf("%2.4f",$knots{$key}{upperbound});
  
}

# We first delete manually some troublesome cases

my @knotlist = sort{ $knots{$a}{sortorder} <=> $knots{$b}{sortorder} } keys( %knots ) ;

print "Now organizing the table by crossing number...\n";

my @bycrossing;

foreach $key ( @knotlist ) {

    if (defined $knots{$key}{cr}) { push(@{ $bycrossing[$knots{$key}{cr}] },$key); }

}

print "There are ".scalar @knotlist." knot types in the database.\n";
print "Of these:\n\n";

my $j;
for($j=0;$j<13;$j++) {

    if (defined $bycrossing[$j]) {

	print scalar @{ $bycrossing[$j] }." are $j crossing knots.\n";
	
    }
}
print "\n";

my @knots;
my @links;
my @straight;
my @kinks;
my @nokinks;
my @primes;
my @composites;
my @compositeknots;
my @compositekinks;
my @compositestraight;

foreach $key ( @knotlist ) {

    if ($knots{$key}{comp} == 1) { 
	
	push(@knots,$key); 
	
    } else { 

	push(@links,$key);

    }
    
    if (defined $knots{$key}{straight}) {

	push(@straight,$key);

    }

    if (defined($knots{$key}{kinks}) and ($knots{$key}{kinks} > 0)) {

      push(@kinks,$key);

    } else {

      push(@nokinks,$key); 
    
    }

    if (defined($knots{$key}{summands})) {

      push (@composites,$key);

      if ($knots{$key}{comp} == 1 && $knots{$key}{cr} <= 12) {

	push(@compositeknots,$key);

      }

    } else {

      push (@primes,$key);

    }

}

open COUNTS, ">${cwd}/tex/fileCounts.tex" or die("Unable to open fileCounts.tex.\n");

print scalar @knots." are knots\n";
print scalar @links." are links\n\n";
print scalar @straight." have straight segments\n";
print scalar @kinks." have kinks\n";
print scalar @primes." are prime\n";
print scalar @composites." are composite\n";
print scalar @compositeknots." are composite knots with <= 12 crossings\n\n";

open MATHEMATICACHECK, ">${cwd}/data/composite_knots_up_to_12.txt" or die("Unable to open composite_knots_up_to_12.txt\n");
print MATHEMATICACHECK "{\n";

my @mentries;

foreach $key (@compositeknots) {

  push(@mentries,"{{\"".join("\",\"",@{$knots{$key}{summands}})."\"}, $knots{$key}{cr}}");

}

print MATHEMATICACHECK join(",",@mentries);
print MATHEMATICACHECK "}\n";

close (MATHEMATICACHECK);

print "The only knots and links without kinks are \n";
foreach ( @nokinks ) {

  print "$_ \n";

}

my @compositeknotkinks;

foreach $key (@kinks) {

  if ($key =~ /\#/ and $knots{$key}{comp} == 1 and $knots{$key}{cr} <= 12) {

    push(@compositeknotkinks,$key);

  }

}

my @compositeknotstraight;

foreach $key (@straight) {

  if ($key =~ /\#/ and $knots{$key}{comp} == 1 and $knots{$key}{cr} <= 12) {

    push(@compositeknotstraight,$key);

  }

}


print COUNTS "\\newcommand\{\\FileCount\}\{".(scalar @knots + scalar @links)."\}\n";
print COUNTS "\\newcommand\{\\KnotCount\}\{".scalar @knots."\}\n";
print COUNTS "\\newcommand\{\\LinkCount\}\{".scalar @links."\}\n";
print COUNTS "\\newcommand\{\\StraightCount\}\{".scalar @straight."\}\n";
print COUNTS "\\newcommand\{\\KinkCount\}\{".scalar @kinks."\}\n";
print COUNTS "\\newcommand\{\\PrimeCount\}\{".scalar @primes."\}\n";
print COUNTS "\\newcommand\{\\CompositeCount\}\{".scalar @composites."\}\n";
print COUNTS "\\newcommand\{\\CompositeKnotCount\}\{".scalar @compositeknots."\}\n";
print COUNTS "\\newcommand\{\\CompositeKinkCount\}\{".scalar @compositeknotkinks."\}\n";
print COUNTS "\\newcommand\{\\CompositeStraightCount\}\{".scalar @compositeknotstraight."\}\n";

my @ok;
my @notok;
my @compositeok;
my @compositesemiok;
my @compositevg;

foreach $key ( @knotlist ) {

  unless (defined $knots{$key}{edges} && defined $knots{$key}{upperbound} && $knots{$key}{residual} ) {
    
    print "Warning: $key doesn't have edge count, upperbound or residual. $knots{$key} \n";
    
  }
  
  if ($massMangle) {

      push (@notok, $key);

  } elsif (($knots{$key}{edges}/$knots{$key}{upperbound} < 8.0 or $knots{$key}{residual} > 0.01)) {
    
    push (@notok, $key);
    
  } elsif ($pushComposites and defined $knots{$key}{summands}) {

    my $summandsum = 0;
    my $summand;
    
    foreach $summand ( @{$knots{$key}{summands}} ) { 

      $summandsum += $knots{standardknottype($summand)}{upperbound};
      
    }

    my $target = $summandsum - (4*3.1415926 - 4)*(scalar @{$knots{$key}{summands}} - 1);

    if ($knots{$key}{upperbound} > $target) {

      push @notok, $key;
      print "ConnectSumConjecture: $key $knots{$key}{upperbound} > $summandsum - ".(4*3.1415926 - 4)*(scalar @{$knots{$key}{summands}} - 1)." = $target \n";

    } else{

      push (@ok, $key);

    } 

  } else {    

      push (@ok, $key);
    
    }

  if (defined ($knots{$key}{summands})) {

    if ($knots{$key}{edges}/$knots{$key}{upperbound} > 8.0 && $knots{$key}{residual} < 0.001) {

      push (@compositevg,$key);

    } 

    if ($knots{$key}{edges}/$knots{$key}{upperbound} > 8.0 && $knots{$key}{residual} < 0.01) {

      push (@compositeok,$key);

    } 

    if ($knots{$key}{edges}/$knots{$key}{upperbound} > 8.0 && $knots{$key}{residual} < 0.025) {

      push (@compositesemiok,$key);

    } 

  }

}

print COUNTS "\\newcommand\{\\DoubleOOneCount\}{".scalar @ok."\}\n";

print "\n";
print scalar @ok." have residual < 0.01 and resolution > 8 (report in alldone.txt)\n";
print scalar @notok. " do not meet these standards (report in tocontinue.txt)\n";
print scalar @compositevg. " of ".scalar @composites." composites have residual < 0.001 and resolution > 8\n";
print scalar @compositeok. " of ".scalar @composites." composites have residual < 0.01 and resolution > 8\n";
print scalar @compositesemiok. " of ".scalar @composites." composites have residual < 0.025 and resolution > 8\n";
print "\n";

if ($#ok > 0) {

    @ok = sort { $knots{$a}{residual} <=> $knots{$b}{residual} } @ok;
    
    print "\n[$knots{$ok[0]}{residual}, $knots{$ok[$#ok]}{residual}] residuals.\n";
    
    my $averageresidual;
    foreach ( @ok ) {$averageresidual += $knots{$_}{residual};}
    $averageresidual /= $#ok;
    print "$averageresidual is the average residual among converged knot types.\n\n";
    
    printf COUNTS "\\newcommand\{\\MinResidual\}\{%4.3g\}\n",$knots{$ok[0]}{residual};
    printf COUNTS "\\newcommand\{\\MaxResidual\}\{%4.3g\}\n",$knots{$ok[$#ok]}{residual};
    printf COUNTS "\\newcommand\{\\AverageResidual\}\{%4.3g\}\n",$averageresidual;
    
    my @tripleos;
    foreach ( @ok ) { if ($knots{$_}{residual} < 0.001) { push @tripleos, $_; } }
    print COUNTS "\\newcommand\{\\TripleOOneCount\}{".scalar @tripleos."\}\n";
    print scalar @tripleos." knots are converged to within 0.001 \n";
    
    my $averagestruts;
    foreach ( @ok ) {if (defined ($knots{$_}{struts})) {$averagestruts += $knots{$_}{struts};}}
    $averagestruts /= $#ok;
    print "$averagestruts is the average number of struts among converged knot types.\n\n";
    
    my $averagemrlocs;
    foreach ( @ok ) {$averagemrlocs += $knots{$_}{mrlocs};}
    $averagemrlocs /= $#ok;
    print "$averagemrlocs is the average number of mrlocs among converged knot types.\n\n";
    
    my $averageedgelength;
    foreach ( @ok ) {$averageedgelength += $knots{$_}{edgelength};}
    $averageedgelength /= $#ok;
    print "$averageedgelength is the average edgelength among converged knot types.\n\n";
    
    my $averageedges;
    foreach ( @ok ) {$averageedges += $knots{$_}{edges};}
    $averageedges /= $#ok;
    print "$averageedges is the average edges among converged knot types.\n\n";
    
    
    print COUNTS "\\newcommand\{\\AverageStruts\}\{".int($averagestruts)."\}\n";
    print COUNTS "\\newcommand\{\\AverageMrlocs\}\{".int($averagemrlocs)."\}\n";
    print COUNTS "\\newcommand\{\\AverageEdges\}\{".int($averageedges)."\}\n";
    
    printf COUNTS "\\newcommand\{\\AverageEdgelength\}\{%4.2g\}\n",$averageedgelength;
    
    print COUNTS "\\newcommand\{\\MatrixDims\}\{".(int($averagestruts) + int($averagemrlocs))." \\times ".3*int($averageedges)."\}\n";
    
    my ($matrixents,$matrixnnz);

    $matrixents = ((int($averagestruts) + int($averagemrlocs))*3*int($averageedges));
    $matrixnnz = (12*int($averagestruts) + 9*int($averagemrlocs));
    
    print COUNTS "\\newcommand\{\\MatrixEnts\}\{$matrixents\}\n";
    print COUNTS "\\newcommand\{\\MatrixNNZ\}\{$matrixnnz\}\n";
    printf COUNTS "\\newcommand\{\\MatrixSparsity\}\{%4.3g\\%%\}\n",100.0*($matrixents - $matrixnnz)/($matrixents);
    
    my @rcondoks;
    my $guy;
    
    foreach $guy ( @ok ) {
	
	if ($knots{$guy}{rcond} != 0) { push @rcondoks, $guy; }

    }

    @rcondoks = sort { (1.0/$knots{$a}{rcond}) <=> (1.0/$knots{$b}{rcond}) } @rcondoks;
    my $mincond;
    my $maxcond;
    $mincond = 1.0/$knots{$rcondoks[0]}{rcond};
    $maxcond = 1.0/$knots{$rcondoks[$#rcondoks]}{rcond};
    
    print "\n[$mincond,$maxcond] condition numbers.\n";
    
    foreach ( @rcondoks ) {$averagercond += 1.0/$knots{$_}{rcond};}
    $averagercond /= $#rcondoks;
    print "$averagercond is the average condition number among converged knot types with nonzero rcond.\n\n";
    
    
    printf COUNTS "\\newcommand\{\\MinCond\}\{%g\}\n",$mincond;
    printf COUNTS "\\newcommand\{\\MaxCond\}\{%g\}\n",$maxcond;
    printf COUNTS "\\newcommand\{\\AverageCond\}\{%g\}\n",$averagercond;
    
}
    
open(TOCONTINUE,">${cwd}/data/tocontinue.txt"); 

my ($ropelength,$residual,$filename,$resolution,$PNAS);

foreach $key (@notok) {

    $PNAS = undef;

    $resolution = $knots{$key}{edges}/$knots{$key}{upperbound};
    $ropelength = $knots{$key}{upperbound};
    $filename = $knots{$key}{filename};
    $residual = $knots{$key}{residual};

    my ($kt,@gr);

    #print "Knot type: $key \n";
    @gr = grep(/^$key$/,@PNAS);

    #print "grep result: @gr \n";

    if (defined $gr[0]) { $PNAS = "PNAS"; } 
    else { $PNAS = ""; }

    write(TOCONTINUE);

}

close TOCONTINUE;

if ($#ok > 0) {

    open(OK,">${cwd}/data/alldone.txt"); 
    
    foreach $key (@ok) {
	
	$resolution = $knots{$key}{edges}/$knots{$key}{upperbound};
	$ropelength = $knots{$key}{upperbound};
	$filename = $knots{$key}{filename};
	$residual = $knots{$key}{residual};
	
	write(OK);
	
    }
    
    close OK;
    
    my $i;
    my $deleted;
    my @nopb;
    my @pb;
    
    foreach $i (0..$#ok) {
	
	unless (defined $knots{$ok[$i]}{prevbound}) { push @nopb, $ok[$i];} 
	else { push @pb, $ok[$i]; }
	
    }
    
#print "Deleted ".scalar @nopb." elements from ok list (@nopb) for having no prevbound...\n";
    
    @pb = sort {
	(0 -$knots{$a}{prevbound} + $knots{$a}{upperbound}) <=> 
	    (0 -$knots{$b}{prevbound} + $knots{$b}{upperbound}) 
	    
    } @pb;
    
    print "Winners over previous data\n";
    print "----------------------------------\n";
    
    my $positive;
    my $negative;
    my $avg;
    
    foreach (0..$#pb) { 
	
	print "$pb[$_] ".$knots{$pb[$_]}{upperbound}." wins by ".100.0*(($knots{$pb[$_]}{prevbound} - $knots{$pb[$_]}{upperbound})/($knots{$pb[$_]}{upperbound}))." \% over the bound {$knots{$pb[$_]}{prevbound}} of $knots{$pb[$_]}{prevcite}.\n";
	
	if ($knots{$pb[$_]}{prevbound} - $knots{$pb[$_]}{upperbound} > 0) {$positive++;} else {$negative++};
	
	$avg += 100*($knots{$pb[$_]}{prevbound} - $knots{$pb[$_]}{upperbound})/($knots{$pb[$_]}{upperbound});
	
    }
    
    $avg /= $#pb;
    
    print "------------------------------------------------------------------------\n";
    print "We beat the bound (by avg of $avg %) in $positive cases and lost in $negative cases.\n";
    print "------------------------------------------------------------------------\n";
    
    print COUNTS "\\newcommand\{\\WonCases}\{$positive\}\n";
    print COUNTS "\\newcommand\{\\LostCases\}\{$negative\}\n";
    printf COUNTS "\\newcommand\{\\AverageWin\}\{%4.3f\}\n",$avg;
    
    $avg =0;
    
#
#now we check against the claimed data
#
    
    my @cb;
    foreach (@pb) { if (defined $knots{$_}{gilbertclaim}) { push @cb, $_; } }
    
    @cb = sort {
	(0 -$knots{$a}{gilbertclaim} + $knots{$a}{upperbound}) <=> 
	    (0 -$knots{$b}{gilbertclaim} + $knots{$b}{upperbound}) 
	    
    } @cb;
    
    print "Winners over previous (claimed) data\n";
    print "----------------------------------\n";
    
    $positive = 0;
    $negative = 0;
    $avg = 0;

    foreach (0..$#cb) { 

	print "$cb[$_] ".$knots{$cb[$_]}{upperbound}." wins by ".100.0*(($knots{$cb[$_]}{gilbertclaim} - $knots{$cb[$_]}{upperbound})/($knots{$cb[$_]}{upperbound}))." \% over the claimed bound {$knots{$cb[$_]}{gilbertclaim}} of $knots{$cb[$_]}{prevcite}.\n";
	
	if ($knots{$cb[$_]}{gilbertclaim} - $knots{$cb[$_]}{upperbound} > 0) {$positive++;} else {$negative++};
	
	$avg += 100*($knots{$cb[$_]}{gilbertclaim} - $knots{$cb[$_]}{upperbound})/($knots{$cb[$_]}{upperbound});;

    }
    

    $avg /= $#cb;
    
    print "-------------------------------------------------------------------------\n";
    print "We beat the claimed bound (by avg of $avg \%) in $positive cases and lost in $negative cases.\n";
    print "-------------------------------------------------------------------------\n";
    
    print COUNTS "\\newcommand\{\\WonClaimCases}\{$positive\}\n";
    print COUNTS "\\newcommand\{\\LostClaimCases\}\{$negative\}\n";
    printf COUNTS "\\newcommand\{\\AverageClaimWin\}\{%4.3f\}\n",$avg;
    
    close COUNTS;
    
    if ($noComposites) {
	
	print "Updating copy of fileCounts.tex in ../rrpaper/\n";
	copy("${cwd}/tex/fileCounts.tex","../rrpaper/fileCounts.tex") or warn("Coudn't refresh the copy of fileCounts in rrpaper dir.\n");
	
    } else {
	
	print "Updating copy of compositeFileCounts.tex in ../rrpaper/\n";
	copy("${cwd}/tex/fileCounts.tex","../rrpaper/compositeFileCounts.tex") or warn("Coudn't refresh the copy of compositeFileCounts in rrpaper dir.\n");

    }

}

my $sourcename;
my $targetname;
my $cwd;

$cwd = getcwd;

print "Recreating ./unfinished directory of ".scalar @notok." files which don't meet quality standards.\n";

my $tempdir;
$tempdir = File::Temp->newdir();
mkdir("$tempdir/unfinished") or die("Couldn't make $tempdir/unfinished");
chdir("${cwd}/tars") or die("Couldn't chdir to tars.\n");

foreach $key (@notok) {

    $resolution = $knots{$key}{edges}/$knots{$key}{upperbound};  
    
    my $tarfile;
    $tarfile = "kl_${key}.tar.gz";
#    print "tar -xzf ${cwd}/tars/$tarfile \n";
    print `tar -xzf ${cwd}/tars/$tarfile`;
    $sourcename = "${cwd}/tars/kl_${key}/$knots{$key}{filename}";

    if (($resolution < 8 || $resolution > 9) && not (defined $pushComposites)) {

        # Search allfiles to see if we've got any runs started at a good resolution.

	copy($sourcename,"temp.vect") or die("Couldn't copy $sourcename to temp.vect");
	`splinevect -r 8 temp.vect`;
	$sourcename = "temp.r8.vect";
	
    } elsif (defined $pushComposites && $resolution < 15) { 

	copy($sourcename,"temp.vect") or die("Couldn't copy $sourcename to temp.vect");
	`splinevect -r 16 temp.vect`;
	$sourcename = "temp.r16.vect";

    }
	
    $targetname = "$tempdir/unfinished/kl_".$key."_unfinished.vect";

    #print "$sourcename -> $targetname ...";
    copy($sourcename,$targetname) or die("failed to copy $sourcename -> $targetname\n");
    #print "ok\n";

    if (defined $knots{$key}{okfiles} ) {

	#print "there are ".scalar @ { $knots{$key}{okfiles} }." alternate files\n";

    } else {

	#print "there are no alternate files.\n";

    }

    if ($sourcename =~ /temp/) { unlink($sourcename) or die("Couldn't unlink $sourcename.\n"); }
    rmtree("${cwd}/tars/kl_${key}/") or die("Couldn't rmtree ${cwd}/tars/kl_${key}/ \n");

}

chdir($tempdir) or die("Couldn't chdir to $tempdir\n");
`tar -czf unfinished.tar.gz unfinished`;
chdir($cwd) or die("Couldn't change back to $cwd");
move("$tempdir/unfinished.tar.gz","${cwd}/data/unfinished.tar.gz") or die("Couldn't move unfinished.tar.gz back to TightKnot");

print "Tar'd results to ${cwd}/data/unfinished.tar.gz\n";
print "Recreating ./unfinished directory of ".scalar @notok." files which don't meet quality standards.\n";

print "Now making shorter list of files not to give up on.\n";

my $fcount;
$fcount = 0;

$tempdir = File::Temp->newdir();
mkdir("$tempdir/unfinished") or die("Couldn't make $tempdir/unfinished");
chdir("${cwd}/tars") or die("Couldn't chdir to tars.\n");


foreach $key (@notok) {

    if ($knots{$key}{residual} < 0.025) {

	$fcount++;

	$resolution = $knots{$key}{edges}/$knots{$key}{upperbound};  

	my $tarfile;
	$tarfile = "kl_${key}.tar.gz";
	print `tar -xzf ${cwd}/tars/$tarfile`;
	$sourcename = "${cwd}/tars/kl_${key}/$knots{$key}{filename}";

	
	if ($resolution < 8 || $resolution > 9) {
	    
	    copy($sourcename,"temp.vect");
	    `splinevect -r 8 temp.vect`;
	    $sourcename = "temp.r8.vect";
	    
	};
	
	$targetname = "$tempdir/unfinished/kl_".$key."_unfinished.vect";
	
	#print "$sourcename -> $targetname ...";
	copy($sourcename,$targetname) or die("failed\n");
	#print "ok\n";
	
	if ($sourcename =~ /temp/) { unlink($sourcename) or die("Couldn't unlink $sourcename.\n"); }
	rmtree("${cwd}/tars/kl_${key}/") or die("Couldn't rmtree ${cwd}/tars/kl_${key}/ \n");

    }

}

chdir($tempdir);
`tar -czf unfinished_possibles.tar.gz unfinished`;
chdir($cwd) or die("Couldn't change back to $cwd");
move("$tempdir/unfinished_possibles.tar.gz","${cwd}/data/unfinished_possibles.tar.gz") or die("Couldn't move unfinished_possibles.tar.gz back to TightKnot");

print "Tar'd $fcount results to ${cwd}/data/unfinished_possibles.tar.gz\n";



format TOCONTINUE_TOP =

     Files that need more work

     Filename                                          Resolution          Residual            Ropelength        PNAS knot?
     ------------------------------------------------  ------------------  ------------------  ----------------  ----------
.

format TOCONTINUE = 
     @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<  @####.############  @####.############  @###.###########  @<<<<<<<<<
     $filename,             $resolution,        $residual,          $ropelength,      $PNAS
.

format OK_TOP =

     Files that are ok.

     Filename               Resolution          Residual            Ropelength
     ---------------------  ------------------  ------------------  ----------------
.

format OK = 
     @<<<<<<<<<<<<<<<<<<<<  @####.############  @####.############  @###.###########
     $filename,             $resolution,        $residual,          $ropelength 
.
