#!/usr/bin/perl
# Authors     : Enrique Amig and Jess Gimnez
# Date        : July 11, 2005
# Description : Responsible for setting up the QARLA Evaluation Framework,
#               given a IQsetup.config file containing information about the
#               source file, set of system files, set of reference files,
#               and optionally the set of metrics to be computed (if any).
#               As a result, XML report files for each given metric are
#               generated for each pair (ref-ref) (sys-ref) (sys-sys).
#               An appropriate IQeval.config file is generated, too.
#
# Usage: IQsetup IQsetup.config IQeval.config
#                   (input)        (output)
#
# ------------------------------------------------------------------------
# ------------------------------------------------------------------------

#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

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

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

my $NARG = 1;
my $DUMMY = "*****";
my $Kdef = .1;  #10% default value

sub get_out
{
   $0 =~ /\/([^\/]*$)/;
   print STDERR "Usage : ", $1, "  [options]  <IQsetup.config>  <IQeval.config>\n";
   print STDERR "                                (input)          (output)\n\n";
   print STDERR "  - print         : print similarities onto IQeval.config (default disabled)\n";
   print STDERR "  - remake        : remake metric computations\n";
   print STDERR "  - JACK          : compute additional similarities required by the JACK measure\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 IQsetup.config 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); } 
}

sub find_nsegments {
   #description _ returns the number of lines in a given file
   #param1  _ filename
   #@return _ <n> number of lines

   my $file = shift;

   my $N = 0;

   open(AUX, "< $file") or die "couldn't open file: $file\n";
   while (<AUX>) { $N++; }
   close(AUX);

   return $N;
}

# ------------------------------------- MAIN ------------------------------------------
my $NARG = 2;

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

my $IQsetup_config;
my $IQeval_config;
my $print = 0;
my $remake = 0;
my $doALL = 0;
my $verbose = 0;

my $ARGOK = 0;
my $i = 0;
while (($i < $ARGLEN) and (!$ARGOK)) {
   my $opt = shift(@ARGV);
   if (($opt eq "-PRINT") or ($opt eq "-print")) { $print = 1; }
   elsif (($opt eq "-REMAKE") or ($opt eq "-remake")) { $remake = 1; }
   elsif (($opt eq "-V") or ($opt eq "-v")) { $verbose = shift(@ARGV); }
   elsif (($opt eq "-jack") or ($opt eq "-JACK")) { $doALL = 1; }
   else {
      if ($opt ne "") {
         $IQsetup_config = $opt;
         if (scalar(@ARGV)) { $IQeval_config = shift(@ARGV); $ARGOK = 1; }
      }
   }
   $i++;
}

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

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

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

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

open(QF, "< $IQsetup_config") or die "couldn't open input file: $IQsetup_config\n";
open(QI, "> $IQeval_config") or die "couldn't open output file: $IQeval_config\n";

print QI "# *****************************************************\n";
print QI "# *                                                   *\n";
print QI "# * NOTE: This file has been automatically generated. *\n";
print QI "# *       It is intended to be modified by the user   *\n";
print QI "# *       to define new metric sets, system sets,     *\n";
print QI "# *       reference sets and segment sets.            *\n";
print QI "# *                                                   *\n";
print QI "# *****************************************************\n";

my $src;
my %Hsystems;
my %Hrefs;
my %Hmetrics;
my @references;
my @systems;
my $Nsegments = 0;
my $name;
my $IQMT = "";
my $doSP = 0;
my $LANG = "ENG";

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 =~ /^\#.*/)) { # line's not a comment
        if ($entry[0] eq "NAME") { print QI "$line\n"; $name = $entry[1]; }
        elsif ($entry[0] eq "source") {
           print QI "$line\n";
           $src = $entry[1];
           $Nsegments = find_nsegments($src);
        }
        elsif ($entry[0] eq "system") {
           print QI "$line\n";
           $systems[$s] = "S".$s;
           $Hsystems{$systems[$s]} = $entry[1];
           $s++;
        }
        elsif ($entry[0] eq "ref") {
           print QI "$line\n";
           $references[$m] = "R".$m;
           $Hrefs{$references[$m]} = $entry[1];
           $m++;
        }
        elsif ($entry[0] eq "IQMT") { print QI "$line\n"; $IQMT = $entry[1]; }
        elsif ($entry[0] eq "LANG") { print QI "$line\n"; $LANG = $entry[1]; }
        elsif ($entry[0] =~ /^doBLEU.*/) {        
           my @subentry = split(/[ ]+/, $entry[0]);
           shift(@subentry);
           if (scalar(@subentry)) { foreach my $m (@subentry) { $Hmetrics{$m} = 1; } }
           else { foreach my $m (keys %{$METRICS::rBLEU}) { $Hmetrics{$m} = 1; } }
        }
        elsif ($entry[0] =~ /^doGTM.*/) {
           my @subentry = split(/[ ]+/, $entry[0]);
           shift(@subentry);
           if (scalar(@subentry)) { foreach my $m (@subentry) { $Hmetrics{$m} = 1; } }
           else { foreach my $m (keys %{$METRICS::rGTM}) { $Hmetrics{$m} = 1; } }
        }
        elsif (($entry[0] =~ /^doMETEOR.*/) or ($entry[0] =~ /^doMTR.*/)) {
           my @subentry = split(/[ ]+/, $entry[0]);
           shift(@subentry);
           if (scalar(@subentry)) { foreach my $m (@subentry) { $Hmetrics{$m} = 1; } }
           else { foreach my $m (keys %{$METRICS::rMETEOR}) { $Hmetrics{$m} = 1; } }
        }
        elsif ($entry[0] =~ /^doNIST.*/) {
           my @subentry = split(/[ ]+/, $entry[0]);
           shift(@subentry);
           if (scalar(@subentry)) { foreach my $m (@subentry) { $Hmetrics{$m} = 1; } }
           else { foreach my $m (keys %{$METRICS::rNIST}) { $Hmetrics{$m} = 1; } }
        }
        elsif (($entry[0] =~ /^doROUGE.*/) or ($entry[0] =~ /^doRG.*/)) {
           my @subentry = split(/[ ]+/, $entry[0]);
           shift(@subentry);
           if (scalar(@subentry)) { foreach my $m (@subentry) { $Hmetrics{$m} = 1; } }
           else { foreach my $m (keys %{$METRICS::rROUGE}) { $Hmetrics{$m} = 1; } }
        }
        elsif ($entry[0] eq "doWER") { $Hmetrics{"1-WER"} = 1; }
        elsif ($entry[0] eq "doPER") { $Hmetrics{"1-PER"} = 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"; }

if (scalar(@references)) { print QI "references=", join(" ", @references), "\n"; }
foreach my $m (@references) { print QI "references_$m=$m\n"; }
if (scalar(@systems)) { print QI "systems=", join(" ", @systems), "\n"; }
foreach my $s (@systems) { print QI "systems_$s=$s\n"; }
if ($Nsegments == 0) { die "[ERROR] empty source file!! (Nsegments=", $Nsegments + 0, ")\n"; }
else { print QI "Nsegments=$Nsegments\n"; print QI "segments=1-$Nsegments\n"; }

print QI "Nmetrics=", scalar(keys %Hmetrics), "\n";
print QI "metrics=", join(" ", sort keys %Hmetrics), "\n";
foreach my $m (sort keys %Hmetrics) { print QI "metrics_$m=$m\n"; }

if ($verbose) {
   print STDERR "----------------------------------------------------------------------------------------\n";
   print STDERR "IQMT path = $IQMT\n";
   print STDERR "----------------------------------------------------------------------------------------\n";
   print STDERR "LANGUAGE = $LANG\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 = 1-$Nsegments\n";
   print STDERR "METRICS = ", join(" ", sort keys %Hmetrics), "\n";
   print STDERR "[", scalar keys %Hmetrics, " metrics]\n";
   print STDERR "----------------------------------------------------------------------------------------\n";
}

# ----------------------------------------------------------------------------------
if (!(-e "./$COMMON::TMP")) { system "mkdir ./$COMMON::TMP"; } #TEMPORARY DIRECTORY
srand(); #random seed initialization
# ----------------------------------------------------------------------------------

if ($verbose) { print STDERR "COMPUTING SIMILARITIES...\n"; }

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

my $parser;

#evaluate each reference against each reference
foreach my $r1 (sort criterion keys %Hrefs) {
   foreach my $r2 (sort criterion keys %Hrefs) {
      if ($r1 ne $r2) {
         METRICS::doMetrics($src, $Hrefs{$r1}, $Hrefs{$r2}, $remake, $r1, $r2, $IQMT, \%Hmetrics, $parser, $LANG, $verbose);
         if ($print) { METRICS::read_write_metrics(*QI, $r1, $r2, \%Hmetrics, $verbose); }
      }
   }
}

#evaluate each system against each reference
foreach my $t (sort criterion keys %Hsystems) {
   foreach my $r (sort criterion keys %Hrefs) {
      METRICS::doMetrics($src, $Hsystems{$t}, $Hrefs{$r}, $remake, $t, $r, $IQMT, \%Hmetrics, $parser, $LANG, $verbose);
      if ($print) { METRICS::read_write_metrics(*QI, $t, $r, \%Hmetrics, $verbose); }
   }
}

if ($doALL) { # do extrawork for JACK computation
   #evaluate each reference against each system
   #foreach my $r (sort criterion keys %Hrefs) {
   #   foreach my $t (sort criterion keys %Hsystems) {
   #      METRICS::doMetrics($src, $Hrefs{$r}, $Hsystems{$t}, $remake, $r, $t, $IQMT, \%Hmetrics, $parser, $LANG, $verbose);
   #      if ($print) { METRICS::read_write_metrics(*QI, $r, $t, \%Hmetrics, $verbose); }
   #   }
   #}

   #evaluate each system against each system
   foreach my $t1 (sort criterion keys %Hsystems) {
      foreach my $t2 (sort criterion keys %Hsystems) {
          if ($t1 ne $t2) {
             METRICS::doMetrics($src, $Hsystems{$t1}, $Hsystems{$t2}, $remake, $t1, $t2, $IQMT, \%Hmetrics, $parser, $LANG, $verbose);
             if ($print) { METRICS::read_write_metrics(*QI, $t1, $t2, \%Hmetrics, $verbose); }
         }
      }
   }
}

close(QI);

if ($verbose) { print STDERR "WRITTEN IQeval config file <$IQeval_config>... [DONE]\n"; }
