#!/usr/bin/perl
# Authors     : Enrique Amig and Jess Gimnez
# Date        : July 11, 2005
# Description : Responsible for evaluating a set of systems inside the QARLA Evaluation Framework,
#               given a proper config file containing information about the
#               source file, set of system files, and set of reference files.
#
# Usage: IQeval [options] IQeval.config
#                           (input)
#
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------

#Copyright (C) 2005 Enrique Amig and Jess Gimnez

#This library is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.

#This library is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
#Lesser General Public License for more details.

#You should have received a copy of the GNU Lesser General Public
#License along with this library; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

# ------------------------------------------------------------------------

#QARLA.pl -op QUEEN -simFile IQ.table -metrics somemetrics -peers systems -models models -topics topics
#QARLA.pl -op QUEEN -simFile IQ.table -metrics metrics -peers systems -models models -topics segments

use strict;
use Data::Dumper;
use IQ::METRICS;
use IQ::QARLA;

my $NARG = 1;

sub get_out
{
   $0 =~ /\/([^\/]*$)/;
   print STDERR "Usage : ", $1, "  [options]  <IQeval.config>\n\n";
   print STDERR "  - M <metrics>         : set of metrics (setname according to IQeval.config)\n";
   print STDERR "                          ['metrics' by default]\n";
   print STDERR "  - S <systems>         : set of systems (setname according to IQeval.config)\n";
   print STDERR "                          ['systems' by default]\n";
   print STDERR "  - R <references>      : set of references (setname according to IQeval.config)\n";
   print STDERR "                          ['references' by default]\n";
   print STDERR "  - T <segments>        : set of segments (setname according to IQeval.config)\n";
   print STDERR "                          ['segments' by default]\n";
   print STDERR "  - G <sys|seg>         : level of granularity\n";
   print STDERR "                          sys - system-level scores (default)\n";
   print STDERR "                          seg - segment-level scores\n";
   print STDERR "  - doOQ                : compute individual metric scores outside QARLA (default disabled)\n";
   print STDERR "  - remake              : remake reports\n";
   print STDERR "  - O <0|1>             : output format\n";
   print STDERR "                          0 - score matrix (default)\n";
   print STDERR "                          1 - ranking lists (on a metric basis)\n";
   print STDERR "  - V <0|1|2>           : verbosity\n";
   print STDERR "                          0 - non-verbose (default)\n";
   print STDERR "                          1 - low verbosity\n";
   print STDERR "                          2 - medium verbosity\n";
   print STDERR "\nExample: $1 -V 1 -doOQ -G seg -O 1 IQeval.config\n\n";
   exit;
}

sub criterion {
  my $A = substr($a, 0, 1); 
  my $B = substr($b, 0, 1);
  if ($A eq $B) { my @lA = split(/[RDS]/, $a); my @lB = split(/[RDS]/, $b); return ($lA[1] <=> $lB[1]); }
  else { return ($A cmp $B); } 
}

# -- main program --
my $NARG = 1;

# check number of argments
my $ARGLEN = scalar(@ARGV);
if ($ARGLEN < $NARG) { get_out(); }


my $M = "metrics";
my $S = "systems";
my $R = "references";
my $T = "segments";
my $G = "sys";
my $O = 0;
my $doOQ = 0;
my $remake = 0;
my $verbose = 0;
my $IQeval_config;

my $ARGOK = 0;
my $i = 0;
while (($i < $ARGLEN) and (!$ARGOK)) {
   my $opt = shift(@ARGV);
   if (($opt eq "-M") or ($opt eq "-m")) { $M = shift(@ARGV); }
   elsif (($opt eq "-S") or ($opt eq "-s")) { $S = shift(@ARGV); }
   elsif (($opt eq "-R") or ($opt eq "-r")) { $R = shift(@ARGV); }
   elsif (($opt eq "-T") or ($opt eq "-t")) { $T = shift(@ARGV); }
   elsif (($opt eq "-G") or ($opt eq "-g")) { $G = shift(@ARGV); }
   elsif (($opt eq "-O") or ($opt eq "-o")) { $O = shift(@ARGV); }
   elsif (($opt eq "-doOQ") or ($opt eq "-dooq")) { $doOQ = 1; }
   elsif (($opt eq "-REMAKE") or ($opt eq "-remake")) { $remake = 1; }
   elsif (($opt eq "-V") or ($opt eq "-v")) { $verbose = shift(@ARGV); }
   else {
      if ($opt ne "") { $IQeval_config = $opt; $ARGOK = 1; }
   }
   $i++;
}

if (($G ne "sys") and ($G ne "seg")) { die "[ERROR] invalid granularity <$G>!!\n"; }

if (!($ARGOK)) { get_out(); }

if ($verbose) {
   $0 =~ /\/([^\/]*$)/;
   print STDERR "----------------------------------------------------------------------------------------\n$METRICS::appname v$METRICS::appversion ($1).\n(C) $METRICS::appyear TALP / UNED.\nWritten by Jesus Gimenez and Enrique Amigo.\n----------------------------------------------------------------------------------------\n";
}

# ------------------------------------- read config file --------------------------

if ($verbose) { print STDERR "READING IQsetup config file <$IQeval_config>..."; }

open(QF, "<$IQeval_config") or die "couldn't open file: $IQeval_config\n";
my %TOOLS;
my @metrics;
my %Hmetrics;
my @systems;
my @references;
my @segments;
my $SEGMENTS;
my $src;
my %Hrefs;
my %Hsystems;
my $IQMT = "";
my $s = 0; my $m = 0;
while (my $line = <QF>) {
   chomp($line);
   if ($line ne "") {
      print QI "$line\n";
      my @entry = split(/ *= */, $line);
      if (!($line =~ /^\#.*/)) {
         if ($entry[0] eq "source") { $src = $entry[1]; }
         elsif ($entry[0] eq "ref") { $references[$m] = "R".$m; $Hrefs{$references[$m]} = $entry[1]; $m++;  }
         elsif ($entry[0] eq "system") { $systems[$s] = "S".$s; $Hsystems{$systems[$s]} = $entry[1]; $s++;  }
         elsif ($entry[0] eq $M) { # metrics
            @metrics = split(" ", $entry[1]);
            my $i = 0; while ($i < scalar(@metrics)) { $Hmetrics{$metrics[$i]} = 1;  $i++; }
         }
         elsif ($entry[0] eq $S) { @systems = split(" ", $entry[1]); } # systems
         elsif ($entry[0] eq $R) { @references = split(" ", $entry[1]); } # references
         elsif ($entry[0] eq $T) { # segments
            $SEGMENTS = $entry[1];
            my @subentry = split(/\, */, $SEGMENTS);
            foreach my $range (@subentry) {
               my @subsubentry = split("-", $range);
               if (scalar(@subsubentry == 1)) { push(@segments, $subsubentry[0]); }
               elsif (scalar(@subsubentry == 2)) {
                  my $i = $subsubentry[0];
                  while ($i <= $subsubentry[1]) { push(@segments, $i); $i++; }
               }
               else { die "[ERROR] invalid segment range!!\n"; }
	    }
         }
         elsif ($entry[0] eq "IQMT") { $IQMT = $entry[1]; }
      }
   }
}
close(QF);

if ($verbose) { print STDERR " [DONE]\n"; }

if ($IQMT eq "") { die "[ERROR] IQMT path undefined!!\n"; }
elsif ($src eq "") { die "[ERROR] source undefined!!\n"; }
elsif (scalar(@references) == 0) { die "[ERROR] set of references undefined!!\n"; }
elsif (scalar(@systems) == 0) { die "[ERROR] set of systems undefined!!\n"; }
elsif (scalar(keys %Hmetrics) == 0) { die "[ERROR] set of metrics undefined!!\n"; }
elsif (scalar(@segments) == 0) { die "[ERROR] set of segments undefined!!\n"; }

if ($verbose) {
   print STDERR "----------------------------------------------------------------------------------------\n";
   print STDERR "IQMT path = $IQMT\n";
   print STDERR "----------------------------------------------------------------------------------------\n";
   print STDERR "SYSTEMS\n";
   print STDERR "-------\n";
   foreach my $r (sort criterion keys %Hsystems) { print STDERR "$r = ", $Hsystems{$r}, "\n"; }
   print STDERR "REFERENCES\n";
   print STDERR "----------\n";
   foreach my $r (sort criterion keys %Hrefs) { print STDERR "$r = ", $Hrefs{$r}, "\n"; }
   print STDERR "----------------------------------------------------------------------------------------\n";
   print STDERR "SOURCE = $src\n";
   print STDERR "SEGMENTS = $SEGMENTS\n";
   print STDERR "METRICS = ", join(" ", sort keys %Hmetrics), "\n";
   print STDERR "----------------------------------------------------------------------------------------\n";
}

$IQMT = $IQMT."/tools";
$IQMT =~ s/\/+/\//g;

if ($doOQ) {
   if ($verbose) { print STDERR "[OUTSIDE QARLA] COMPUTING SCORES...\n"; }
   foreach my $t (sort METRICS::criterion @systems) {
      METRICS::doMultiMetrics($src, $Hsystems{$t}, \%Hrefs, $remake, $t, $IQMT, \%Hmetrics, $verbose);
   }
   print STDERR " [DONE]\n";
}

my $IQ = QARLA::start(\@metrics, \@segments, \@systems, \@references, $verbose);

if ($O == 0) { #score matrix
   my @header;
   if ($doOQ) {
      foreach my $m (sort @metrics) { push(@header, sprintf("%-8s", $m)); }
   }
   if ($G eq "sys") { # G == 'sys'
      printf "%-8s %s %-8s %-8s\n", "SYS", join(" ", @header), "QUEEN", "IQ";
   }
   else { # G == 'seg'
      printf "%-16s %s %-8s %-8s\n", "SYS:SEG", join(" ", @header), "QUEEN", "IQ";
   }
   print "\n";
   foreach my $t (sort METRICS::criterion @systems) {
      my %OQ;
      if ($doOQ) {
         my @auxSYS = ($t);
         METRICS::read_metrics(\@metrics, \@auxSYS, \@references, \@segments, \%OQ, $G, $verbose);
      }
      METRICS::print_metrics(\%OQ, $IQ, $t, $G, \@metrics, \@segments, \@references, $doOQ, $verbose);
   }
}
elsif ($O == 1) { #ranking lists
   my %OQ;
   if ($doOQ) { METRICS::read_metrics(\@metrics, \@systems, \@references, \@segments, \%OQ, $G, $verbose); }
   METRICS::print_rankings(\%OQ, $IQ, $G, \@metrics, \@segments, \@systems, \@references, $doOQ, $verbose);
}
else { die "[ERROR] UNKNOWN OUTPUT MODE <$O>!!\n"; }
