# # (gH)   -_-  galgexec.pl  ;  TimeStamp (unix) : 21 Janvier 2018 vers 20:36

## ajouter un numéro en random ?

#######################################################################
#                                                                     #
# exécution controlée d'un algorithme sans erreur détectée            #
#                                                                     #
#######################################################################

#
#  on passe en paramètre le nom de l'exercice et le nom du fichier algorithme
#  on utilise le fichier XML de configuration de l'exercice pour tester
#  les exécutions
#
#  on renvoie le nombre de runs et le pourcentage de réussite
#
#  exemple d'utilisation : perl -w galgexec.pl minmax.xml minmax.alg
#

use strict   ;
use warnings ;

### 0.  test des paramètres

my $nbArgs = $#ARGV ;

if ($nbArgs<1) {
    print "Il manque des paramètres. Syntaxe : php galgexec.php XML ALGORITHME\n" ;
    print "STOP.\n\n" ;
    exit(-1) ;
} ; # fin si sur le nombre de paramètres

my $xmlFic = $ARGV[0] ;

if (!-e $xmlFic) {
    print "Fichier XML $xmlFic non vu.\n" ;
    print "STOP.\n\n" ;
    exit(-2) ;
} ; # fin si sur l'existence du fichier XML

my $algFic = $ARGV[1] ;

if (!-e $algFic) {
    print "Fichier ALGORITHME $algFic non vu.\n" ;
    print "STOP.\n\n" ;
    exit(-3) ;
} ; # fin si sur l'existence du fichier ALG

### 1.  on lit les fichiers

##  1.1 on lit le fichier de configuration

open(FICXML,"<$xmlFic"); ;
my $xmldoc = "" ;
while (my $ligXml=<FICXML>) {
  chomp($ligXml) ;
  $xmldoc .= $ligXml ;
} ; # fin tant que
close(FICXML) ;

#print "XML : " ;
#print $xmldoc."\n" ;
#print "\n" ;

my $nbExec = 0 ;
$xmldoc =~ /executions="([0-9]+)?"/ ;
$nbExec = $1 ;

##  1.2 on lit le fichier algorithme et on vérifie que son analyse ne produit pas d'erreur

my $baseNomFichier = substr($algFic,0,rindex($algFic,".")) ;
my $errFile = $baseNomFichier.".err" ;
my $lstFile = $baseNomFichier.".lst" ;
my $cmd = "galg -a $algFic " ;
#print "CMD  : $cmd \n" ;
system($cmd) ;

if (!-e $errFile) {
    print "Fichier de résultat de l'analyse de l'algorithme $errFile non vu.\n" ;
    print "STOP.\n\n" ;
    exit(-3) ;
} ; # fin si sur l'existence du fichier XML

open(FICERR,"<$errFile"); ;
my $ligErr = <FICERR> ;
chomp($ligErr) ;
close(FICERR) ;
my $resAnalyse = ($ligErr eq "0 erreur")  ;

if (!$resAnalyse) {

    print "Fichier ALGORITHME $algFic incorrect, erreur(s) détectée(s) via $errFile.\n" ;
    #print "Consulter le fichier $lstFile ci-dessous pour voir les erreurs.\n" ;

    #my $cmde = "cat $errFile " ;
    #print "CMD  : $cmde \n" ;
    #system($cmde) ;

    print "STOP à cause des erreurs.\n\n" ;
    exit(-3) ;

} ; # fin si

### 2.  on boucle sur les exécutions à tester

my $indExec = 0 ;
my @tabRes  ;
my @nbvRes  ;
while ($xmldoc =~ m|<execution.*?>(.*?)</execution>|gs) {

  $indExec++ ;
  #print "\n" ;
  #print "Exécution numéro $indExec\n" ;
  #print "====================\n\n" ;
  #print "EXECUTION $1 \n" ;
  my $execution = $1 ;
  $execution =~ m|<entrees>(.*?)</entrees>.*?<sorties>(.*?)</sorties>|gs ;
  #print "  ENTREES $1 \n" ;
  #print "  SORTIES $2 \n" ;
  my $entrees = $1 ;
  my $sorties = $2 ;
  my %entVars ;
  my %resVars ;
  while ($entrees =~ m|<variable(.*?)>|gs) {
    my $ligVariable = $1 ;
    $ligVariable =~ /nom="(.*?)".*?valeur="(.*?)"/ ;
    my $variable = $1 ;
    my $valeur   = $2 ;
    #print "         ENT $variable = $valeur \n" ;
    $entVars{$variable} = $valeur ;
  } ; # fintant que sur les entrées
  while ($sorties =~ m|<variable(.*?)>|gs) {
    my $ligVariable = $1 ;
    $ligVariable =~ /nom="(.*?)".*?valeur="(.*?)"/ ;
    my $variable = $1 ;
    my $valeur   = $2 ;
    #print "         SOR $variable = $valeur \n" ;
    $resVars{$variable} = $valeur ;
  } ; # fintant que sur les sorties
  $nbvRes[$indExec] = keys %resVars ;

##  2.1 on prépare le fichier algorithme à exécuter

    my $algFile = "galgExec-TEMP.alg" ;
    system("rm -f $algFile") ;
    my $debExec = "--exec--start" ;
    my $finExec = "--exec--end" ;

    my $debutAlg = "\n\n" ;
    $debutAlg .= "##### galgExec.alg ; début 1/2 de test d'exécution\n" ;
    $debutAlg .= "##### auteur GALG \n" ;
    foreach my $nom (sort keys %entVars) {
      $debutAlg .= "AFFECTER $nom <-- $entVars{$nom} \n" ;
    } ; # fin pour chaque variable
    foreach my $nom (sort keys %resVars) {
      $debutAlg .= "AFFECTER $nom <-- ".'"variable_non_définie"'."\n" ;
    } ; # fin pour chaque variable
    $debutAlg .= "##### galgExec.alg ; début 2/2 de test d'exécution\n" ;

    my $orgAlg = "\n\n" ;
    open(FICALG,"<$algFic"); ;
    while (my $ligAlg=<FICALG>) {
      $orgAlg .= $ligAlg ;
    } ; # fin tant que
    close(FICALG) ;

    my $finAlg = "\n\n" ;
    $finAlg .= "##### galgExec.alg ; fin 1/2 de test d'exécution\n" ;
    $finAlg .= "\n" ;
    $finAlg .= 'ECRIRE "'.$debExec.'"'."\n" ;
    foreach my $nom (sort keys %resVars) {
      $finAlg .= 'ECRIRE "'.$nom.'" , '.$nom."\n" ;
    } ; # fin pour chaque variable
    $finAlg .= 'ECRIRE "'.$finExec.'"'."\n" ;
    $finAlg .= "\n" ;
    $finAlg .= "##### galgExec.alg ; fin 2/2 de test d'exécution\n" ;

    #print $debutAlg . $orgAlg . $finAlg ;
    my $algText = $debutAlg . $orgAlg . $finAlg . "\n\n" ;
    open(TMPALG,">$algFile") ;
    print TMPALG $algText ;
    close(TMPALG) ;

##  2.2 on exécute

    my $resFile = "galgExec-res.txt" ;
    $cmd     = "timeout  -s SIGTERM 5s galg -a $algFile -o perl -x > $resFile " ;
    #print "CMD $cmd.\n" ; # execution $nbExec \n" ;
    system($cmd) ;

    if (!-e $resFile) {
        print "Fichier RESULTAT $resFile non vu.\n" ;
        print "STOP.\n\n" ;
        exit(-4) ;
    } ; # fin si sur l'existence du fichier XML


    my $resTxt  = "" ;
    my $lectVars = 0 ;
    my %exeVars ;
    open(FICRES,"<$resFile") ;
    while (my $ligRes=<FICRES>) {
      chomp($ligRes) ;
      if ($ligRes eq $finExec) { $lectVars = 0 ; } ;
      if ($lectVars==1) {
        my @varTab = split(/\s+/,$ligRes) ;
        $exeVars{ $varTab[0] } = $varTab[1] ;
      } ; # fin si lecture des variables
      if ($ligRes eq $debExec) { $lectVars = 1 ; } ;
    } ; # fin tant que
    close(FICRES) ;

##  2.3 on compare les résultats

    my $nbSolOK = 0 ;
    foreach my $laVar (sort keys %resVars) {
      if ($exeVars{ $laVar}) {
        if ($exeVars{$laVar} eq $resVars{$laVar}) { $nbSolOK++ ; } ;
      } # fin si la variable existe
    } # fin pour chaque variable
    $tabRes[ $indExec ] = $nbSolOK ;

} # fin tant que sur les exécutions

### 3.  on fournit un compte-rendu des exécutions

print "\n";
print "Résultats de l'évaluation\n" ;
print "=========================\n\n" ;
print "Exécution      NbVar  BonnesRéponses\n" ;

my $nbExecOK = 0 ;
for (my $indExec=1;$indExec<=$nbExec;$indExec++) {

    if ($tabRes[ $indExec ]== $nbvRes[ $indExec ]) {
        $nbExecOK++ ;
    } ; # fin si

    print sprintf("%3d",$indExec)." / ".$nbExec ;
    print sprintf("       %3d",$nbvRes[$indExec]) ;
    print sprintf("       %3d",$tabRes[$indExec]) ;
    print "\n" ;

} ; # fin pour indExec
print "\n" ;

my $tauxR = 100*$nbExecOK/$nbExec ;
print "Avec $nbExecOK exécutions réussies sur $nbExec, le taux de réussite est de ".sprintf("%3d",$tauxR)." %.\n" ;
print "\n" ;
print "\n" ;

## fin normale de script
