                     
                     
                     
// Copyright 1992, David Perelman-Hall & Jamshid Afshar

#include "filename.h"

#ifdef DOS
#include <strstrea.h>
#else
#include <strstream.h>
#endif

#include <assert.h>
#include <iostream.h>
#include <fstream.h>
#include <ctype.h>
#include "dico.h"
#include "strategy.h"
#include "memory.h"
#include "flux.h"

#include "arc.h"
#include "rules.h"
#include "edge.h"
#include "chart.h"
#include "agenda.h"
#include "init.h"
#include <time.h>

/*#include <libc.h>
#include <osfcn.h>
#include <sysent.h>
#include <unistd.h>
#include "users3/these/christo/dialvir/dive/include/sys.h"
pour usleep sur neptune -> ne marche pas
*/


#include "util.cc"
#include "loc.cc"
#include "assoc.cc"
#include "action.cc"
#include "utilisateur.cc"
#include "agent_virtuel.cc"
#include "controleur.cc"


LexList*  dictionnaire;		   //OBJET GLOBAL pour les vinf (action)

#define MAX_MOTS_BUFFER 100


Controleur controleur;	//OBJET GLOBAL

class Bilan {
  public :
  char syntaxique[10];
  char syntaxique_dernier_terme[30];
  variable_globale_bilan(){
    CP(syntaxique,"");
    CP(syntaxique_dernier_terme,"");
  }
};

Bilan variable_globale_bilan;
     // -> OBJET GLOBAL pour tester la non comprehension d'un enonce


#include "sizemax.h"

#ifdef __BCPLUSPLUS__
extern unsigned  _stklen=50000U;
#endif

unsigned _stack = 50000U;


//-----------------------------------------------------------------------------------


#ifdef __BCPLUSPLUS__
#include <sys/timeb.h>
#endif



#ifdef CC
#define difftime(a,b)   (a-b)
#elif GCC
#define difftime(a,b)   (a-b)
#endif



void majuscule(char * s)
{
 for(;*s!=0;s++)
  if ((*s & 128)==0)
   *s=toupper(*s);
}

//------------------------------------------------------------------------------


void InitChart(Chart& chart)

{
   chart.SetReste(chart.GetChaineInitiale());
   chart.NbHoleToInsert=chart.MAX_SUITE_HOLE;
   chart.SetModif(FALSE);
}

void InitParse(const NOEUD& goal,Chart& chart, RuleList& rules,int debut=0)

{
   if (chart.INCREMENTAL_HOLE==TRUE)
    chart.max_hole=0;
   else
    chart.max_hole=chart.MAXIMUM_HOLE;


   if (chart.strategie==TOP_DOWN)
     chart.Top_Down_Init(goal,chart.GetAgenda(),rules,debut);

}




//----------------------------------------------------------------------------------



int old_debut=-1;
int old_debut_a_succes=0;
//boolean
bool StepParse(/*const NOEUD& goal,*/
		   RuleList& rules,
		   RuleList& locution,
		   LexList& dico,
		   Chart& chart,
		     int num_locuteur,
		   int debut=0 )
{

   DAG GOAL;
   if (chart.SEGMENTATION==TRUE)
    GOAL["constituant"]="oui";
   else
    GOAL["CAT"]="PH";

   do
    {

		 if ( !chart.GetAgenda().isEmpty() )
		  {
		    EdgeNode * edge = chart.GetAgenda().getNext();
		    chart.add( edge, chart.GetAgenda(), rules/*, locution*/ );
		    return TRUE;
		  }

	    if (chart.SEGMENTATION==TRUE)
	     {
	       debut=chart.NextComplement();
            }
	    else
	      debut=0;
       if ((debut  !=   old_debut) && (debut<=chart.last_vertex()))
		{
         old_debut=debut;
		 InitParse(GOAL,chart,rules,debut);
		 if  ( !chart.GetAgenda().isEmpty() ) // il s'agit d'un cas non encore analysé
		  continue;
		}
    if (debut>chart.last_vertex())
     strcpy(chart.mot_refuse,chart.nouveau_mot);
	else if (chart.SEGMENTATION==TRUE)// NextComplement n'a rien detecte d'anormal sinon la condition precedente aurait ete accomplie
	  strcpy(chart.mot_refuse,"");
	else if ( (chart.strategie==BOTTOM_UP) || (chart.strategie==TOP_DOWN) )
	 {
       int trans=chart.transitivite(GOAL,debut);
       if (trans == chart.last_vertex())
        {
		  strcpy(chart.mot_refuse,"");
		}
	   else /*  if ( trans == chart.last_vertex()-1 )  */
		strcpy(chart.mot_refuse,chart.nouveau_mot);
     }
    else   // on ne refuse rien en Mode CLASSIQUE
     strcpy(chart.mot_refuse,"");


	if (strlen(chart.mot_refuse)!=0)
	 {
	  assert(chart.max_hole<=chart.MAXIMUM_HOLE);
	  assert(chart.MAXIMUM_HOLE>=0);
	  assert(chart.max_hole>=0);

	  if (chart.max_hole==chart.MAXIMUM_HOLE)
	   {
	    chart.NbHoleToInsert=0;
	    chart.retire_derniere_category();
	    if (strcmp(chart.mot_refuse,"HOLE")!=0)  // on a echoue sur un mot et non sur un HOLE
	      chart.ResetReste();
	    flux_de_sortie<<"Erreur !!! Le mot "<<chart.mot_refuse<<" est refusé ...\n";
	    flux_de_sortie.flush();
        //debut=chart.NextComplement(old_debut_a_success,chart.last_vertex()+1); // on recalcule le point d'attache
            if (eg (chart.mot_refuse,"."))
              CP(variable_globale_bilan.syntaxique,"echec");
	    else
              CP(variable_globale_bilan.syntaxique,"approximation");
	    return TRUE;
	   }
	  else
	   {
	    flux_de_sortie<<"old max_hole = "<<chart.max_hole<<"\n";
	    flux_de_sortie.flush();
	    chart.Allow_New_Hole(chart.GetAgenda());
	strcpy(chart.mot_refuse,"");
	    flux_de_sortie<<"new max_hole = "<<chart.max_hole<<"\n";
	    flux_de_sortie.flush();
	    continue; // presque pareil que return TRUE...
	   }
	 }
//      else if (chart.test_success(goal))
//       return FALSE;
//      else
//       {
	  //flux_de_sortie<<"OK : \n";
	  //flux_de_sortie.flush();
	  //flux_de_sortie<<string.length()<<" "<<string;
//       }

     //char nouveau_mot[20];

////!!!!          do
////!!!!           {
//          if ( (erreur==FALSE) && (chart.nb_hole_consecutif()<chart.MAX_SUITE_HOLE) )
		 // rajouter quele chose du style:   && (chart.is_hole(chart.last_vertex())==FALSE)
		 // ou bien (strcmp(chart.nouveau_mot,"HOLE")==0)
	    if   (chart.NbHoleToInsert>0)
	       {
		     strcpy(chart.nouveau_mot,"HOLE");
		     flux_de_sortie<<"HOLE\n";
		     flux_de_sortie.flush();
	       }
	    else
	     {
//#ifndef VC
	 // flux_de_sortie<<"\n";
	      if (chart.strategie==TOP_DOWN)
		   chart.Cat_Attendues();
	 //     if (chart.point_possible()==TRUE)
	 //  flux_de_sortie<<"POINT possible\n";
	//  flux_de_sortie<<"\n";
//#endif
	      if (!chart.GetReste().isEmpty())
	       {
		NOEUD cat=chart.GetReste().pop();
		strcpy(chart.nouveau_mot,cat.Symbole());
		//flux_de_sortie<<chart.nouveau_mot<<"\n";
		//flux_de_sortie.flush();
	       }
	      else
	      do
	       {

/*NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN Nouvelle version */     

  static char* buffer[MAX_MOTS_BUFFER] ;
  static int nb_mots_ds_buffer =0;
  static int indice_buffer=0;
  static int nb_ent=0;  
  static int indice_ent=1;
  char entree[LONGUEUR_LIGNE_MAX];
  char valeur_ajoutee[LONGUEUR_LIGNE_MAX];
  char *mots = NULL;
  int loc_finale=0;
  int loc_inclus_et_egal=0;

  if (nb_mots_ds_buffer != 0) {
      nb_ent=nb_mots_ds_buffer; indice_ent=1;
      nb_mots_ds_buffer=0; indice_buffer=0;
  }
  do
  {
    do 
    {
      if (nb_ent == 0){
//	utilisateur.dit(entree);
	controleur.entend_mot(num_locuteur,entree);
      } 
      else {
//deb("nb_ent=");debi(nb_ent);
         strcpy(entree,buffer[indice_ent++]);
         nb_ent--;
      }
      buffer[indice_buffer++]=strdup(entree);    
      nb_mots_ds_buffer++;
//deb("2");
      if (mots==NULL)
          mots=strdup(entree); 
      else { 
         sprintf(valeur_ajoutee,"%s_%s",mots,entree);
         mots=&valeur_ajoutee[0];
      }      
//deb("les mots sont :");debn(mots);
    } while (controleur.locutions.mots_debutent_locution2(mots,loc_finale,
             loc_inclus_et_egal));    
    if ( loc_inclus_et_egal !=0 ){
       nb_mots_ds_buffer=1; indice_buffer=1;
       buffer[0]=strdup(mots);
//deb("une loc inclue et egale :");debn(buffer[0]);
    }
  } while ( loc_inclus_et_egal != 0 );

  if ( loc_finale !=0 ) {
     nb_mots_ds_buffer=0; indice_buffer=0;
     strcpy(chart.nouveau_mot,mots);
//deb("locution : ");
     cout<<mots<<" ";cout.flush();

  }
  else {
     nb_mots_ds_buffer--; indice_buffer=0;
     strcpy(chart.nouveau_mot,buffer[0]);    
//deb("Ce que je garde : ");
     cout<<buffer[0]<<" ";cout.flush();
  }                            
//  if (strcmp(chart.nouveau_mot,".")==0) debn(" ");

	   }
	  while(strlen(chart.nouveau_mot)==0);
	     }

	chart.SetModif(TRUE);

	    if ((chart.nouveau_mot[0]=='c')||(chart.nouveau_mot[0]=='e')
	       || (chart.nouveau_mot[0]=='0'))
	     {
	      int indice=0;
	      int max_indice=chart.last_vertex()-1;
	      while ((indice<=max_indice)&&(chart.vertex_is_hole(indice)==TRUE))
	       indice++;
	      if (indice>max_indice)
	       {
		flux_de_sortie<<"Plus de mots a retirer !!!\n";
		flux_de_sortie.flush();
	       }
	      else
	       {
		flux_de_sortie<<"Effacement\n";
		flux_de_sortie.flush();
		chart.retire_dernier_mot();
	       }
	      chart.NbHoleToInsert=0;
	      return TRUE;
	     }
	     else if (eg(chart.nouveau_mot,"Z")
		    ||eg(chart.nouveau_mot,"QUIT"))
	      { cout<<'\n';cout.flush();return FALSE;}
	    else
	     {
	      if (strcmp(chart.nouveau_mot,"HOLE")==0)
	   chart.NbHoleToInsert--;
	      else
	   chart.NbHoleToInsert=chart.MAX_SUITE_HOLE;
	      chart.GetAgenda().ajoute_edge_nouveau_mot(chart.nouveau_mot,rules,locution,dico,chart);

	     }
    }
   while (TRUE);
}



int ParseC(const NOEUD& goal,
	       RuleList& rules,
	       RuleList& locution,
	       LexList& dico,
	       Chart& chart, int num_locuteur )
{
 CP(variable_globale_bilan.syntaxique,"OK");
 do
  {
//deb("global=");debn(variable_globale_bilan.syntaxique_dernier_terme);
   if (StepParse(/*goal,*/rules,locution, dico,chart,num_locuteur)==FALSE)
    return FALSE;
   if (eg(variable_globale_bilan.syntaxique,"echec")) return FALSE; // la phrase se termine par un point mais celui-ci est refuse.
  }
 while ( (chart.GetAgenda().isEmpty()==FALSE) || (chart.test_success(goal)==FALSE));
 return TRUE;
}



//------------------------------------------------------------------------

boolean init(RuleList& rules,  RuleList& locution, LexList& dico,Chart& chart)
{
 //      chart.strategie=BOTTOM_UP;
       chart.strategie=TOP_DOWN;
       chart.INCREMENTAL_HOLE=FALSE;
       chart.MAXIMUM_HOLE=0;
       chart.MAX_SUITE_HOLE=0;
       chart.SEGMENTATION=TRUE;

   char c;
   char s[20];

   do
    {
     flux_de_sortie<<"Methode (T -> Top Down  ;  B -> Bottom Up ; C -> Classique)\n";
     flux_de_sortie.flush();
     flux_d_entree>>s;
     c=s[0];

     c=tolower(c);

     if (c=='b')
      {
       flux_de_sortie<<"Methode ascendante (Bottom Up)\n";
       flux_de_sortie.flush();
       chart.strategie=BOTTOM_UP;
      }
     else if (c=='t')
      {
       flux_de_sortie<<"Methode descendante (Top Down)\n";
       flux_de_sortie.flush();
       chart.strategie=TOP_DOWN;
      }
     else if (c=='c')
      {
       flux_de_sortie<<"Methode Classique (Bottom Up)\n";
       flux_de_sortie.flush();
       chart.strategie=CLASSIQUE;
      }
    }
   while ((c!='t')&&(c!='b')&&(c!='c'));

   do
    {
     flux_de_sortie<<"Gestion des mots manquants (I -> Incremental ; G -> Global)\n";
     flux_de_sortie.flush();
     flux_d_entree>>s;
     c=s[0];

     c=tolower(c);

     if (c=='i')
      {
       flux_de_sortie<<"Gestion incrementale\n";
       flux_de_sortie.flush();
       chart.INCREMENTAL_HOLE=TRUE;
      }
     else if (c=='g')
      {
       flux_de_sortie<<"Gestion globale\n";
       flux_de_sortie.flush();
       chart.INCREMENTAL_HOLE=FALSE;
      }
    }
   while ((c!='g')&&(c!='i'));

   do
    {
     flux_de_sortie<<"Gestion des Segments (O -> Oui ; N -> Non)\n";
     flux_de_sortie.flush();
     flux_d_entree>>s;
     c=s[0];

     c=tolower(c);

     if (c=='o')
      {
       flux_de_sortie<<"Analyse par Segments\n";
       flux_de_sortie.flush();
       chart.SEGMENTATION=TRUE;
      }
     else if (c=='n')
      {
       flux_de_sortie<<"Analyse sans Segment\n";
       flux_de_sortie.flush();
       chart.SEGMENTATION=FALSE;
      }
    }
   while ((c!='o')&&(c!='n'));


   flux_de_sortie<<"Nombre maximal de mots manquants dans une phrase ? ";
   flux_de_sortie.flush();
   flux_d_entree>>chart.MAXIMUM_HOLE;

   if (chart.MAXIMUM_HOLE>1)
    {
     flux_de_sortie<<"Nombre maximal de mots manquants consecutifs ? ";
     flux_de_sortie.flush();
     flux_d_entree>>chart.MAX_SUITE_HOLE;
    }
   else
    chart.MAX_SUITE_HOLE=chart.MAXIMUM_HOLE;

   if (chart.MAX_SUITE_HOLE>chart.MAXIMUM_HOLE)
    chart.MAX_SUITE_HOLE=chart.MAXIMUM_HOLE;


   // READ IN THE RULES
         

   if (chart.SEGMENTATION==TRUE)
     {
       if (rules.read(RULE_SEG_FILE)==FALSE)
        return FALSE;
     }   
   else
     if (rules.read(RULE_PARSE_FILE)==FALSE)
      return FALSE;
   if (dico.read(LEXLIST_FILE)==FALSE)
     return FALSE;
   if (locution.read(LOCUTION_FILE)==FALSE)
     return FALSE;
     
   chart.Init();

   return TRUE;
}


//--------------------------------------------------------------------------


//------------------------------------------------------------------------------------


#ifndef VC



const char *default_file = "parse.in";

void read_string(char* nom, int lg)

#define caractere_bidon 'b'

{
#ifdef CC
 flux_d_entree.getline(nom,lg);
#else
#ifdef QUICKWIN
 flux_d_entree.getline(nom,lg);
#else
 flux_d_entree.putback(caractere_bidon);
 flux_d_entree.getline(nom,lg);
 for(int i=0; nom[i]!=0 ; i++)
   nom[i]=nom[i+1];
#endif
#endif
}


#include "depend.h"

int fonction_entendre(RuleList rules,LexList dico,Chart* & pChart,const Edge* &PO,int num_locuteur)
{ 

  RuleList locution;
    
  NOEUD Goal;
  Goal["CAT"]="PH";
       pChart->strategie=TOP_DOWN;
//       pChart->strategie=BOTTOM_UP;
       pChart->INCREMENTAL_HOLE=TRUE;
       pChart->MAXIMUM_HOLE=0;
       pChart->MAX_SUITE_HOLE=0; 
       pChart->SEGMENTATION=FALSE;

   InitChart(*pChart);
   InitParse( Goal,*pChart,rules);
   if (!ParseC(Goal,rules,locution,dico,*pChart,num_locuteur)) 
	return FALSE; 
     
   EdgeInfoRec rec;

   PO=pChart->GetFirstParse(Goal,rec);  
   int nb_analyse=0;
   do {
     nb_analyse++;
   } while (pChart->GetNextParse(rec)!=NULL);
   cout<<"--> "<<nb_analyse<<" arbre"; 
   if (nb_analyse>1)cout<<"s"; 
   cout<<" syntaxique";
   if (nb_analyse>1)cout<<"s.\n"; else cout<<".\n";
//  deb("-- [ Nombre d'analyse: ");debi(nb_analyse);
  
  const Edge* PB=pChart->GetFirstParse(Goal,rec);
  if (eg(valeur((Edge *)PB,"R_FIN FIN","MOT"),"#"))
    for(int nbb=0;nbb!=nb_analyse;PB=pChart->GetNextParse(rec))
        cout<<"#############ANALYSE "<<++nbb<<":\n"<<((Edge *)PB)->parse();  
  return TRUE;
}

int Controleur::entend(Chart* & pChart,const Edge* &PO)
{
  return fonction_entendre(*(Ma.rules),*(Mon.dico),pChart,PO,Mon.locuteur);
}

int Agent_virtuel::analyse_syntaxiquement(Chart* & pChart,const Edge* &PO)
{
  return fonction_entendre(*(Ma.rules),*(Mon.dico),pChart,PO,Mon.locuteur);
}

void gerer_dialogue(RuleList &rules,LexList &dico,int argc)
{
  randomize();
  controleur.init(getenv("USER"),getenv("DIVEINPUT"),getenv("DIVENAME"),
 		&rules,&dico,argc,getenv("DIVESOUND"));
	// Utilisation des 4 variables d'environnement :
	// 	- USER, DIVEINPUT, DIVENAME, DIVESOUND

DEB4
  controleur.affiche_locuteurs();
DEB5
  Edge* PO;
  Chart *pChart;
  int num_1=1,num_2=1; 
  char* replique;
  char reponse[LONGUEUR_TEXTE_MAX]="";
  do {
    if (argc!=0)replique=controleur.ecoute(num_1); 
//deb("la replique:");debn(replique);
    if (controleur.locuteur==-1){ // -1=utilisateur
		//marche pas pour tous les agents??
      if(!controleur.donne_la_main_au_destinataire(replique,reponse)){
        pChart=new Chart(); //cout<<sizeof(*pChart);
        assert(pChart!=NULL);
        if (controleur.entend(pChart,PO)){
//debn(variable_globale_bilan.syntaxique);
             controleur.cherche_destinataire(PO);
             controleur.donne_la_main_au_destinataire(pChart,replique,reponse);
             controleur.verifie_creation_agent();
        }
        else if (eg(variable_globale_bilan.syntaxique,"echec")) {
             char echec[]=
"{0 excusez_moi 0 excusez_moi_mais} {Je_ne_comprends_pas pouvez_vous_répéter pouvez_vous_répéter_SVP}";
              traiter_au_hasard(echec);
              controleur.fait_parler_agent(echec);
              controleur.efface_replique();
              controleur.ajoute_replique_dialogue(replique,num_1);
        }
        delete pChart; //cout<<"apres:"<<sizeof(*pChart);
      }
      controleur.ajoute_replique_dialogue(replique,num_1);
      if(controleur.affiche_reponse(reponse,num_1,num_2))
        controleur.ajoute_reponse_dialogue(replique,num_1);
      num_1++; 
    }  
    else {
/*    pChart=new Chart(); cout<<sizeof(*pChart);
      assert(pChart!=NULL);
      controleur.entend(pChart,PO);        
      delete pChart; //cout<<"apres:"<<sizeof(*pChart);
*/    
      controleur.fait_parler_agent(replique);
      controleur.efface_replique();
      controleur.ajoute_replique_dialogue(replique,num_1);
    }
    //cout<<"memoire linguistique :"<<sizeof(mem_ling_commune)<<'\n';
//  } while (num_1 != 254 || !eg(getenv("DIVENAME"),"BOB"));
  } while (TRUE);
}




int main(int argc, char *argv[]){

 flux_d_entree=cin;
 flux_de_sortie=cout;


 NOEUD_SEQUENCE * pInput=new NOEUD_SEQUENCE();
 assert(pInput!=NULL);
    
  RuleList rules;
  LexList  dico;

  dico.read("lexlist");
  rules.read("rulelist");

  dictionnaire=&dico;
  gerer_dialogue(rules,dico,argc);

  lexique.clear();//on peut remettre à 0 les lexique car pChart et pInput
  lexique_arc.clear();  // qui les utilisaient ont ete detruits
   
  flux_de_sortie<<"c'est fini !!!\n";
  flux_de_sortie.flush();
return 0;


}



#endif




