/*--------------------------------------------------------------------
Mise a jour des catalogues...
----------------------------------------------------------------------*/
 


#include "msjour.h"

int OCC, VRAI_NB_PATTERNS;
char **codes; /* bibcodes pour les articles */
void init_codes();

static char usage[] = "Usage: program -u unit_file -t pattern_file newpattern_file" ;
static char help[] = "\
  -t : definit le fichier qui contient tous les catalogues (defaut: pattern)\n\
  -u : fichier qui contient les vecteurs des unites (defaut: units)\n\
  newpattern_file : contient les nouveaux catalogues (default: stdin)\n\
"; 


main(int argc, char **argv)
{
static FILE *fu, *ft, *fe ;
int no_pattern, composante;
char *arg ;
    while(--argc > 0) {
        arg = *++argv ;
        if (arg[0] == '-') switch(arg[1]) {
          case 'h':
             printf("%s\n%s", usage, help) ;
             exit(0) ;
          case 'u': fu = fopen(*++argv, "r"); argc-- ; 
            if (fu) continue ;
            perror(*argv) ; exit(1) ;
          case 't': ft = fopen(*++argv, "r"); argc-- ; 
            if (ft) continue ;
            perror(*argv) ; exit(1) ;
          default:
            fprintf(stderr, "****Mauvais argument: %s\n", arg) ;
            exit(1) ;
        }
        fe = fopen(arg, "r") ;
        if (!fe) { perror(arg) ; exit(1) ; }
    }
 
    if (! fu) {
	fu = fopen("units", "r") ;
	if (!fu)  { perror("units") ; exit(1); }
    }
    if (! ft) {
	ft = fopen("pattern", "r") ;
	if (!ft)  { perror("pattern") ; exit(1); }
    }
    if (!fe) fe = stdin ;


/*****************************/
 
  
  INIT=0;
  OCC=0; 
  /* lecture des donnees qui ont servi a l'apprentissage  */    
  init_pattern(ft);


  VRAI_DIM_PATTERNS=DIM_PATTERNS;

  INIT=0;
  OCC=1;

  init_pattern(fe);
  init_codes(fe);   /* numeros catalogues  */

  load_units(fu);

  /* maintenant: calcul des noeuds gagnants  */
  all_winners();
}



/***************************************************************************
 Lit dans chaque ligne du fichier specifie, les numeros de 
           mot-cle et les place dans le tableau "patterns" 
***************************************************************************/

void init_pattern(entree)
FILE *entree;
{
   char *fin, *debut ;
   int i,no_pattern, max = 0, no_kw = 0, max2 = 0 ;
   float comp,sum;
   char fname2[255];
   
    if(INIT==0) 
      { 
          init_tableaux(entree);
          INIT=1;
      }
  


/*--- mise a zero de pattern ----------------------------------------------*/
   for(no_pattern=0;no_pattern<NB_PATTERNS;no_pattern++)
       for(no_kw=0;no_kw<MAX_KWD;no_kw++) patterns[no_pattern][no_kw]=0;
   no_pattern=0;
   max_kwd=0;


   

/*----Initialisation du tableau occurences----*/
 if(OCC==0)
   {
    for(i=1;i<DIM_PATTERNS;i++)
       {
        occurences[i][0]=0.0;
       }
   }


   while((fgets(chaine,100,entree)!=NULL)&&(no_pattern<NB_PATTERNS))
   {
      no_kw=0;
      fin=strstr(chaine,chaine);
      while(fin!=NULL)   
      {       
          if((debut=strstr(chaine," ")) != NULL)   debut=debut+1;
          else                                     break ;
          strcpy(chaine,debut);
          fin=strstr(chaine," ");  
          i=atoi(chaine); 
	  /*     printf("i=%d ",i);*/
          if(no_kw>max)    max=no_kw;


 
          if(no_kw<=MAX_KWD)
          {
            if(i>max2)  max2=i;
	  
            patterns[no_pattern][no_kw]=i;
         if(OCC==0)   occurences[i][0]+=1.0;/* ne pas se tromper, ici, i est le numero de mot-cle et 
                                     no_kw est le no d'apparition du mot cle dans la liste
                                     de l'article...*/
          }
          else
             printf("\nL'article no %d contient au moins %d articles (>%d)\n",no_pattern,no_kw,MAX_KWD);
          no_kw++;    /*--- on passe au mot-cle suivant ---*/
      }
      no_pattern++;   /*--- on passe a la reference suivante ---*/
   }

   /*----Calcul des composantes des patterns-----*/
   for(no_pattern=0;no_pattern<NB_PATTERNS;no_pattern++)/*Initialisation*/
     {
      for(i=0;i<MAX_KWD;i++)
	{
         vraies_composantes_patt[no_pattern][i]=0.0;
	}
     }
  
   for(no_pattern=0;no_pattern<NB_PATTERNS;no_pattern++)
     {
     i=0;
     sum=0.0;
     while((no_kw=patterns[no_pattern][i])!=0)
       {
        sum=occurences[no_kw][0];
        
	/*  printf("%f\n",sum);*/
        fflush(stdout);



        if(OCC==0) VRAI_NB_PATTERNS=NB_PATTERNS;
        comp=(float)log((float)VRAI_NB_PATTERNS/occurences[no_kw][0]);
        vraies_composantes_patt[no_pattern][i]=comp;

        sum+=comp*comp;
        i++;
       }
     for(i=0;i<MAX_KWD;i++)/*normalisation*/ 
       {
         vraies_composantes_patt[no_pattern][i]/=sqrt(sum);
       
       }
      }

   /*fclose(entree);*/
   
}


/*****************************************************************
               charge les unites sauvegardees auparavant
*****************************************************************/

void load_units(FILE *entree)
{
char  chaine[12];
int no_unit,no_composante;
float x;

  for(no_unit=0;no_unit<NB_X*NB_Y;no_unit++)
   {
    for(no_composante=1;no_composante<DIM_PATTERNS;no_composante++)
     {
       /*   fgets(chaine,11,entree);
        x=atof(chaine);
        LEs exposants ne sont pas reconnus avec atof */
   fscanf(entree,"%e",&x);

   /*   printf("      x=%f\n",x);*/
        units[no_unit][no_composante]=x;
    
     }
 
   } 
  /* fclose(entree);*/
   rewind(entree);

}

/*************************************************************************************

***********************************************************************/
void init_tableaux(entree)
FILE *entree;
{
   char *fin, *debut ;
   int i,no_pattern = 0, max = 0, no_kw = 0, max2 = 0 ;
   float comp,sum;
   char fname2[255];

  


/*----  Lecture du fichier ---------------------------------------------*/
  while((fgets(chaine,100, entree)!=NULL))
   {
      no_kw=0;
      fin=strstr(chaine,chaine);
      while(fin!=NULL)   
      {       
          if((debut=strstr(chaine," ")) != NULL)   debut=debut+1;
          else                                     break ;
          strcpy(chaine,debut);
          fin=strstr(chaine," ");  
          i=atoi(chaine); 
	  /*     printf("i=%d ",i);*/
          if(no_kw>max)    max=no_kw; 
       
            if(i>max2)  max2=i;
                 
          no_kw++;    /*--- on passe au mot-cle suivant ---*/
      }
      no_pattern++;   /*--- on passe a la reference suivante ---*/
   

 
       } 


 /*  printf("\n\nNombre maximal de mot-cles par article:%5d",max); */
   
/*  MAX_KWD = max+1; c'est le vrai nombre */ 

       /* mais il faut une composante de plus pour pattern */
    MAX_KWD = max+2;
 /*  printf("\nArticles enregistres:                  %5d",no_pattern); */
       NB_PATTERNS = no_pattern;
     if(OCC==0)   DIM_PATTERNS = max2+1;


/*printf("\nMot-cles definis:                      %5d\n",max2); */




 rewind(entree);




patterns = malloc_tableau(NB_PATTERNS, MAX_KWD,sizeof(int));

units = malloc_tableau(NB_Y*NB_X, DIM_PATTERNS, sizeof(float));
vraies_composantes_patt = malloc_tableau(NB_PATTERNS, MAX_KWD, sizeof(float));

if(OCC==0) occurences = malloc_tableau(DIM_PATTERNS, 2, sizeof(float));

/*INIT=1;*/
}


/***************************************************************************
.PURPOSE  :  Alloue la place memoire necessaire a un tableau a une ou deux
             dimensions.
.RETURN   :  Renvoie l'adresse du pointeur sur ce tableau.
.EXAMPLE  :
             float * * tab1;
             char * tab2;

              tab1 = malloc_tableau(100, 12, sizeof(float));
              tab1[i][j]=12,34;
                 pour un tableau 100x12 de flottants.

              tab2 = malloc_tableau(10, 0, sizeof(char));
              tab2[i]='w';
                 pour un tableau de caracteres a une dimension.
*****************************************************************************/

void * malloc_tableau(x,y,contenu)
int x, y, contenu;
{
void * *  pere;
void * fils;
int i, j;


if(y != 0)
  {

    pere = (void ** ) malloc(sizeof(void*)*x);
    if (pere == NULL) printf("out of memory\n");

  for(i=0;i<x;i++)
    {
    fils = (void * )malloc(contenu*y);
    if (fils == NULL) printf("out of memory\n");
    pere[i] = fils;

    }
  }
else
  {
   pere = (void *) malloc(x*contenu);


  }
return(pere);


}




/****************************************************************
                         WINNER
****************************************************************/
int get_winner(no_pattern)
   int no_pattern;
{ 
   int no_unit,winner=0;
   float max=0.0,tmp;


   for(no_unit=0 ; no_unit<NB_X*NB_Y ; no_unit++)
   {
       tmp=dot(no_unit,no_pattern);

/*printf("no_unit=%d no_pattern=%d dot=%f  max=%f\n",no_unit,no_pattern,tmp,max);*/
       if(max<tmp)
       {
         max=tmp;
         winner=no_unit;
       }
   }
   return(winner);  
  }


/****************************************************************
                         produit scalaire
****************************************************************/
float dot(no_unit,no_pattern)
   int no_unit,no_pattern;
{
   int i, no_composante = 0;
   float sum = 0. ;



  
   while((i=patterns[no_pattern][no_composante])!=0)
   {
     sum=sum+units[no_unit][i]*vraies_composantes_patt[no_pattern][no_composante];
      
     /* sum=sum+units[no_unit][i];*/

           no_composante++;
   }
  
 
 
    
   return(sum);
}

/*****************************************************************************
  Calcul des no_unit dans lesquelles sont classes les objets.
******************************************************************************/
void all_winners()
{
int winner, no_pattern;

  for(no_pattern=0; no_pattern<NB_PATTERNS; no_pattern++)
    {
    winner=get_winner(no_pattern);
    printf("%s : %d\n", codes[no_pattern], winner);
    }

}


/**********************************************************************
  stocke les codes (BIBCODES POUR LES ARTICLES)
**********************************************************************/

void init_codes(entree2)
FILE *entree2;
{
  char *pt;
  char chaine[200];
  int i;

 codes = malloc_tableau(NB_PATTERNS, 0, sizeof(pt));
  rewind(entree2);
  i=0;
   for(i=0; i<NB_PATTERNS; i++)
    {
      fgets(chaine,199, entree2);    
      pt = strstr(chaine, " ");
      *pt='\0';     
      codes[i]=malloc(sizeof(char)*(pt-chaine+1));
      strcpy(codes[i], chaine);
      fflush(stdout);
    }
   

}
