#! /usr/bin/perl

use warnings;
use POSIX;
#
# Takes in input the readytogo folder, the random seed and the #instances and prepares a directory structure containing
# selected instances (created as symbolic links)
#
sub printUsage()
{
   return "Usage: makeCompetitionSet inDir outDir seed instancesPerBenchmark\n";
}

$inDir  = $ARGV[0] || die printUsage();
$outDir = $ARGV[1] || die printUsage();
$seed   = $ARGV[2] || die printUsage();
$instances = $ARGV[3] || die printUsage();

%tracks = ( 'M&S' => 16, 'System' => 27 );

$norm = 255;

sub round
{
   return sprintf("%.0f",$_[0]);
}
sub min ($$) { $_[$_[0] > $_[1]] }
sub max ($$) { $_[$_[0] < $_[1]] }
#
#  Generates a RC4 byte stream from the seed. Skips first 1000 bytes, to avoid known RC4
#  poor randomization in the initial stream
#
$n = $instances + 1;
open(RC4, "cat /dev/zero | openssl rc4 -K $seed -e | od -j 1 -w1 -vt u1 -N $n | cut -s -d' ' -f2- |");

$start = <RC4>;
chomp $start;
print "START: $start ";
for ($i = 0; $i < $instances; $i++)
{
   $perturb[$i] = <RC4>/$norm * 3 - 1.5;  #perturbation will range from -1.5 to 1.5
}
close RC4;
print "PERTURBATIONS:".join(' ',@perturb)."\n";

qx{mkdir $outDir} unless -e"$outDir";
$t = 0;
foreach $track (sort keys %tracks)
   {
      $dir = "t".sprintf("%02d",++$t);
      qx{mkdir $outDir/$dir} unless -e"$outDir/$dir";
   }
foreach $bench (qx{find $inDir -mindepth 1 -maxdepth 1 -type d})
{
   chomp $bench;
   @instancesB = qx{find $bench -type f};
   ($benchID) = $bench =~ /b(\d\d)/;  
   $step = @instancesB / $instances;
   $startB = floor ( $step*$start/$norm );
   for ( $i = 0; $i < $instances; $i++ )
   {
      $instanceNum[$i] = round(max(1,min($startB + $i * $step + $perturb[$i] , @instancesB-1)));
      if ($i > 0 && ($instanceNum[$i] <= $instanceNum[$i-1]))
      {
          $instanceNum[$i] = $instanceNum[$i-1]+1;
      }
   }
   print "B:$benchID Step:$step Start:$startB \n";
   $t = 0;
   foreach $track (sort keys %tracks)
   {
      $tdir = "t".sprintf("%02d",++$t);
      print "=== TRACK $tdir ===\n";
      if ( $benchID <= $tracks{$track} )
      {
 	   $opath = "$outDir/$tdir/b$benchID";
           qx{mkdir $opath} unless -e"$opath";
           qx{mkdir $opath/instances} unless -e"$opath/instances";
           foreach ($i = 0; $i < $instances; $i++)
           {
               chomp $instancesB[$i];
               $fn = sprintf("%04d",$instanceNum[$i]);
               #print "b$benchID/$fn:$instanceNum[$i]\n";
 	       @source = grep { /$fn/ } @instancesB;
               $source = $source[0]; chomp $source;
               $filename = qx{basename $source}; chomp $filename;
               $dest = "$outDir/$tdir/b$benchID/instances/$filename";	
               print "ln -s $source $dest\n";
               print qx"ln -s $source $dest";
           }
      }
      else { print "b$benchID not selected for Track $tdir\n" };
   }
}
