
// This file is part of the Herezh++ application.
//
// The finite element software Herezh++ is dedicated to the field
// of mechanics for large transformations of solid structures.
// It is developed by Gérard Rio (APP: IDDN.FR.010.0106078.000.R.P.2006.035.20600)
// INSTITUT DE RECHERCHE DUPUY DE LÔME (IRDL) <https://www.irdl.fr/>.
//
// Herezh++ is distributed under GPL 3 license ou ultérieure.
//
// Copyright (C) 1997-2022 Université Bretagne Sud (France)
// AUTHOR : Gérard Rio
// E-MAIL  : gerardrio56@free.fr
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License,
// or (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
//
// For more information, please consult: <https://herezh.irdl.fr/>.

/************************************************************************
 *     DATE:        28/01/2004                                          *
 *                                                                $     *
 *     AUTEUR:      G RIO   (mailto:gerardrio56@free.fr)                *
 *                                                                $     *
 *     PROJET:      Herezh++                                            *
 *                                                                $     *
 ************************************************************************
 *     BUT:   Gestion  de divers bloc courant du fichier de lecture .   *
 *            Cas où ces blocs sont relatif au chargement, et héritent  *
 *             de bloc classiques.                                      *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *                                                                      *
 *     VERIFICATION:                                                    *
 *                                                                      *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *     !        !            !                                    !     *
 *                                                                $     *
 *     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''     *
 *     MODIFICATIONS:                                                   *
 *     !  date  !   auteur   !       but                          !     *
 *     ------------------------------------------------------------     *
 *                                                                $     *
 ************************************************************************/
#ifndef BLOC_CHARGE_T_H
#define BLOC_CHARGE_T_H

#include "BlocCharge.h"
#include "ConstMath.h"
#include "CharUtil.h"


/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

//================================================
/// class template:    cas d'un bloc  avec charge 
//================================================
template <class Bloc_particulier>
class BlocCharge : public Bloc_particulier  
{
   // surcharge de l'operator de lecture
   friend istream & operator >> (istream & entree, BlocCharge<Bloc_particulier> & coo)
     { // tout d'abord la classe mère
       entree >> ((Bloc_particulier&)(coo));
       // puis les valeurs propres
       string toto; string nomOuNombre;
       entree >> toto >> coo.co_charge >> toto >> coo.echelle;
       // lecture t_min en fonction d'une fonction nD ou pas
       entree >> toto >> nomOuNombre;
       if (nomOuNombre != "fct_nD:")
        {coo.t_min = ChangeReel(nomOuNombre);
         coo.nom_fnD_t_min = "";coo.fnD_t_min=NULL;
        }
       else
        {entree >> coo.nom_fnD_t_min;};
       // lecture t_max en fonction d'une fonction nD ou pas
       entree >> toto >> nomOuNombre;
       if (nomOuNombre != "fct_nD:")
        {coo.t_max = ChangeReel(nomOuNombre);
         coo.nom_fnD_t_max = "";coo.fnD_t_max=NULL;
        }
       else
        {entree >> coo.nom_fnD_t_max;};
//       entree >> toto >> coo.t_min >> toto >> coo.t_max;
       entree >> toto >> coo.precedent >> coo.attribut
              >> toto >> coo.f_charge;
       return entree;      
     }
   // surcharge de l'operator d'ecriture
   friend ostream & operator << (ostream & sort, const BlocCharge<Bloc_particulier> & coo)
     { // tout d'abord la classe mère
       sort << ((const Bloc_particulier&)(coo));
       // puis les valeurs propres 
       sort << "\n nom_courbe_de_charge: " << coo.co_charge << " echelle: " << coo.echelle;
       sort << " temps_mini= " ;
       if (coo.nom_fnD_t_min == "")
            {sort << coo.t_min;}
       else {sort << " fct_nD: " << coo.nom_fnD_t_min ;};
       sort   << " temps_maxi= ";
       if (coo.nom_fnD_t_max == "")
            {sort << coo.t_max;}
       else {sort << " fct_nD: " << coo.nom_fnD_t_max ;};
//       sort << " temps_mini= " << coo.t_min << " temps_maxi= " << coo.t_max;
       sort << " activité_actuelle: " << coo.precedent << " attribut: "<< coo.attribut
            << " f_charge: "<< coo.f_charge
            << endl;
        return sort;      
     } 

  public :
    // VARIABLES PUBLIQUES :
     // stockage d'un element 
     // class conforme a la specif de T de la class LectBloc_T
     
     // Constructeur    
        BlocCharge () :   // par defaut
          Bloc_particulier(),co_charge(""),echelle(1.),f_charge("")
          ,t_min(0.),t_max(ConstMath::tresgrand),precedent(false)
          ,attribut("_")
          ,nom_fnD_t_min(""),fnD_t_min(NULL),nom_fnD_t_max(""),fnD_t_max(NULL)
           {};
        BlocCharge (const BlocCharge& a) : // de copie
          Bloc_particulier(a),co_charge(a.co_charge),echelle(a.echelle)
          ,t_min(a.t_min),t_max(a.t_max),precedent(a.precedent)
          ,attribut(a.attribut),f_charge(a.f_charge)
          ,nom_fnD_t_min(a.nom_fnD_t_min),fnD_t_min(a.fnD_t_min)
          ,nom_fnD_t_max(a.nom_fnD_t_max),fnD_t_max(a.fnD_t_max)
           {};
     // destructeur   
        ~BlocCharge () {};
      

 
     //-------- les méthodes constantes --------------
        // retourne le nom de la courbe de charge
        const string & NomCourbeCharge() const {return co_charge;};
        // retourne le nom de la fonction nD
        const string & NomF_charge() const {return f_charge;};
        // retourne l'échelle
        const double Echelle_courbe() const {return echelle;};
        // retourne la chaine de caratères attribut: si = "_" , signifie qu'il n'y a pas d'attribut
        const string & Attribut() const {return attribut;};
        // affichage des informations
        void Affiche() const ;
        // surcharge des operateurs
        bool operator == ( const BlocCharge& a) const; 
        BlocCharge& operator = (const  BlocCharge& a); 
        bool operator != ( const BlocCharge& a) const;
        // retour du statut de validation
        // vrai signifie que l'état enregistré est actif
        bool Etat_validation() const {return precedent;};

     //------------- les méthodes qui modifient -------------
        // lecture d'un bloc
        void Lecture(UtilLecture & entreePrinc);  
        // Validation on non de l'activité de la charge
        void Validation(const double& temps) {precedent = Temps_actif(temps);};
 
        // affichage et definition interactive des commandes
        // attribut : donne un attribut éventuel à afficher dans les choix
        void Info_commande_BlocCharge(ostream & sort,string attribut = "_");

        // mise en place de l'association des fonctions nD, dont ensuite on garde un pointeur
        // en retour indique si l'association est ok
        bool Mise_en_place_des_fonction_nD(const LesFonctions_nD& lesFonctionsnD);
        // retourne un booléen qui indique si oui ou non le temps passé en paramètre
        // est situé entre le temps min et maxi du ddllim
        bool Temps_actif(const double& temps)
          {if (fnD_t_min != NULL)
              {if (fnD_t_min->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
                { t_min = (fnD_t_min->Valeur_pour_variables_globales())(1);}
               else
                {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisee pour donner le temps mini "
                      << "  seule la dependance aux grandeurs globales est autorisee ";
                 cout << "\n fonction nD: "; fnD_t_min->Affiche();this->Affiche();
                 Sortie(1);
                };
             };
           if (fnD_t_max != NULL)
              {if (fnD_t_max->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
                { t_max = (fnD_t_max->Valeur_pour_variables_globales())(1);}
               else
                {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisee pour donner le temps maxi "
                      << "  seule la dependance aux grandeurs globales est autorisee ";
                 cout << "\n fonction nD: "; fnD_t_max->Affiche();this->Affiche();
                 Sortie(1);
                };
             };
          if ((t_min < temps) && (temps <= t_max))
               return true;
          else return false;
         };
        // ramène vrai si le temps est inférieur au temps actif
        // ou si d'une part le temps n'est pas actif et qu'au pas précédent
        // il n'était pas également actif (? je ne comprends plus pourquoi j'ai fait cette fonction)
        bool Pas_a_prendre_en_compte(const double& temps)
          {if (fnD_t_min != NULL)
              {if (fnD_t_min->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
                { t_min = (fnD_t_min->Valeur_pour_variables_globales())(1);}
               else
                {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisee pour donner le temps mini "
                      << "  seule la dependance aux grandeurs globales est autorisee ";
                 cout << "\n fonction nD: "; fnD_t_min->Affiche();this->Affiche();
                 Sortie(1);
                };
             };
           if (fnD_t_max != NULL)
              {if (fnD_t_max->Nom_variables().Taille() == 0) // cas où il n'y a que des variables globales
                { t_max = (fnD_t_max->Valeur_pour_variables_globales())(1);}
               else
                {cout << "\n *** erreur en retour de l'utilisation d'une fonction nD utilisee pour donner le temps maxi "
                      << "  seule la dependance aux grandeurs globales est autorisee ";
                 cout << "\n fonction nD: "; fnD_t_max->Affiche();this->Affiche();
                 Sortie(1);
                };
             };
           if ((temps <= t_min) || ((temps > t_max) && !precedent))
              return true;
           else return false;
        };


   protected :
	    string  co_charge; // nom d'une courbe de charge éventuelle
     string  f_charge; // nom d'une fonction nD utilisant des variables globales et autres
	    double echelle;
     double t_min,t_max; // temps mini et maxi de durée des ddl imposés
     string nom_fnD_t_min; // nom éventuelle de la fonction associée
     Fonction_nD* fnD_t_min; // fonction nD associée, éventuelle
     string nom_fnD_t_max; // nom éventuelle de la fonction associée
     Fonction_nD* fnD_t_max; // fonction nD associée, éventuelle
     int precedent; // pour la description de l'évolution du ddlLim
     string attribut; // une chaine de caractère qui sert pour donner une
               // information particularière au Bloc_particulier associé
               // apparaît uniquement si le mot clé: attribut_ est présent
               // et est constitué par la chaine qui suit ce mot cle
 }; 
/// @}  // end of group


/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

/// lecture d'un bloc
template <class Bloc_particulier>
void BlocCharge<Bloc_particulier>::Lecture(UtilLecture & entreePrinc)
    { // tout d'abord lecture de la classe mère
      Bloc_particulier::Lecture(entreePrinc);
      // on regarde s'il y a un attribut ou non, si oui on le lit
      attribut="_"; // init par défaut
      if (strstr(entreePrinc.tablcar,"ATTRIBUT_")!=NULL)
       // cas où il y a un attribut
       { string nom;
         *(entreePrinc.entree) >> nom ;
         if (nom != "ATTRIBUT_")
            {cout << "\n erreur de syntaxe en lecture de l'attribut "
                  << " on attendait le mot cle ATTRIBUT_ et on a lu"
                  << nom << endl;
             if (ParaGlob::NiveauImpression() > 4)
                cout << "\n BlocCharge::Lecture(.. " << endl ;
             entreePrinc.MessageBuffer("**erreur**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);          
             }
         else
          {*(entreePrinc.entree) >> attribut;};
       };
      
      // puis lecture des infos de la classe
      // on regarde s'il ne s'agit pas d'une courbe de charge imposée
      if (strstr(entreePrinc.tablcar,"COURBE_CHARGE:")!=NULL)
        {// cas d'une courbe de charge, on se positionne sur le mot clé
         string titi4; bool bonnefin4=false; 
         while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur
                        (!(entreePrinc.entree->eof())))
             { // lecture du prochain mot     
              *(entreePrinc.entree) >> titi4 ;
              if (titi4 == "COURBE_CHARGE:"){bonnefin4=true; break;};
             };
         if (!bonnefin4)    
            {cout << "\n erreur de syntaxe en lecture du nom de la courbe ";
             cout << "\n BlocCharge::Lecture(.. " << endl ;
             entreePrinc.MessageBuffer("**erreur**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);          
            }
         else
             //lecture du nom de la courbe de charge
            { *(entreePrinc.entree) >> co_charge; };
         // on récupère l'échelle éventuellement
         string toto1;
         if(strstr(entreePrinc.tablcar,"ECHELLE:")!=0)
           { // cas où il y a un facteur d'échelle
             *(entreePrinc.entree)  >> toto1;
             if (toto1 != "ECHELLE:")
               {cout << "\n erreur de syntaxe en lecture du facteur d'echelle ";
                cout << "\n BlocCharge::Lecture(.. " << endl ;
                entreePrinc.MessageBuffer("**erreur**");
                throw (UtilLecture::ErrNouvelleDonnee(-1));
                Sortie(1);          
                }
              // lecture du facteur
              *(entreePrinc.entree)  >> echelle; 
           }; //-- fin récup de l'échelle
        }; //-- fin récup de la courbe de charge

      // on regarde s'il n'y a pas une fonction nD de chargement
      if (strstr(entreePrinc.tablcar,"Fonction_nD_CHARGE:")!=NULL)
        {// cas d'une fonction de charge, on se positionne sur le mot clé
         string titi4; bool bonnefin4=false; 
         while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur
                        (!(entreePrinc.entree->eof())))
             { // lecture du prochain mot     
              *(entreePrinc.entree) >> titi4 ;
              if (titi4 == "Fonction_nD_CHARGE:"){bonnefin4=true; break;};
             };
         if (!bonnefin4)    
            {cout << "\n erreur de syntaxe en lecture du nom de la fonction nD ";
             cout << "\n BlocCharge::Lecture(.. " << endl ;
             entreePrinc.MessageBuffer("**erreur**");
             throw (UtilLecture::ErrNouvelleDonnee(-1));
             Sortie(1);          
            }
         else
             //lecture du nom de la fonction de charge
            { *(entreePrinc.entree) >> f_charge; };
         // on récupère l'échelle éventuellement
         string toto1;
         if(strstr(entreePrinc.tablcar,"ECHELLE:")!=0)
           { // cas où il y a un facteur d'échelle
             *(entreePrinc.entree)  >> toto1;
             if (toto1 != "ECHELLE:")
               {cout << "\n erreur de syntaxe en lecture du facteur d'echelle ";
                cout << "\n BlocCharge::Lecture(.. " << endl ;
                entreePrinc.MessageBuffer("**erreur**");
                throw (UtilLecture::ErrNouvelleDonnee(-1));
                Sortie(1);
                }
              // lecture du facteur
              *(entreePrinc.entree)  >> echelle;
           }; //-- fin récup de l'échelle
        }; //-- fin récup de la courbe de charge


      // lecture éventuelle des temp mini et maxi : mais on doit doir d'abord passer éventuellement des infos
      
      if (strstr(entreePrinc.tablcar,"TEMPS_MINI=") != 0) 
         // on lit jusqu'à trouver le mot clé
        { string titi; bool bonnefin=false; 
          while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur
                        (!(entreePrinc.entree->eof())))
             { // lecture du prochain mot     
              *(entreePrinc.entree) >> titi ;
              if (titi == "TEMPS_MINI="){bonnefin=true; break;};
             };
          if (!bonnefin)    
             {cout << "\n erreur inconnue  de syntaxe en lecture du temps mini";
              cout << "\n BlocCharge::Lecture(.. " << endl ;
              entreePrinc.MessageBuffer("**erreur**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
             }          
          else
             //lecture du temps mini
            { string nomOuNombre;
              *(entreePrinc.entree) >> nomOuNombre;
              if (nomOuNombre != "fct_nD:")
               {t_min = ChangeReel(nomOuNombre);
                nom_fnD_t_min = "";fnD_t_min=NULL;
               }
              else
               {*(entreePrinc.entree) >> nom_fnD_t_min;};
            //*(entreePrinc.entree) >> t_min;
            };
        }; //-- fin du cas temps mini  
      
      if (strstr(entreePrinc.tablcar,"TEMPS_MAXI=") != 0) 
         // on lit jusqu'à trouver le mot clé
        { string titi; bool bonnefine=false; 
          while ((!entreePrinc.entree->rdstate())&& // lecture tant qu'il n'y a pas d'erreur
                        (!(entreePrinc.entree->eof())))
             { // lecture du prochain mot     
              *(entreePrinc.entree) >> titi ;
              if (titi == "TEMPS_MAXI="){bonnefine=true; break;};
             };
          if (!bonnefine)    
             {cout << "\n erreur inconnue  de syntaxe en lecture du temps maxi";
              cout << "\n BlocCharge::Lecture(.. " << endl ;
              entreePrinc.MessageBuffer("**erreur**");
              throw (UtilLecture::ErrNouvelleDonnee(-1));
              Sortie(1);
             }          
          else
             //lecture du temps maxi
            { string nomOuNombre;
              *(entreePrinc.entree) >> nomOuNombre;
              if (nomOuNombre != "fct_nD:")
               {t_max = ChangeReel(nomOuNombre);
                nom_fnD_t_max = "";fnD_t_max=NULL;
               }
              else
               {*(entreePrinc.entree) >> nom_fnD_t_max;};
              //*(entreePrinc.entree) >> t_max;              
            };
        }; //-- fin du cas temps maxi  
     }
     /// @}  // end of group


/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

/// affichage des infos
template <class Bloc_particulier>
void BlocCharge<Bloc_particulier>::Affiche()  const 
  { // tout d'abord affichage des infos de la classe mère
    Bloc_particulier::Affiche();
    // puis des infos propres
    cout << "\n nom_courbe_de_charge: " << co_charge << " echelle: " << echelle;
    cout << " temps_mini= ";
    if (nom_fnD_t_min == "")
         {cout << t_min;}
    else {cout << " fct_nD: " << nom_fnD_t_min ;};
    cout   << " temps_maxi= ";
    if (nom_fnD_t_max == "")
         {cout << t_max;}
    else {cout << " fct_nD: " << nom_fnD_t_max ;};
    cout << " activite_actuelle: " << precedent << " attribut: "<< attribut << endl
         << " f_charge: "<< f_charge;
   }
    /// @}  // end of group


/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

/// surcharge des operateurs
template <class Bloc_particulier>
bool BlocCharge<Bloc_particulier>::operator == ( const BlocCharge<Bloc_particulier>& a) const
   { //if (!(((Bloc_particulier)(*this)) == ((const Bloc_particulier&)(a)) )) 
     if (   !(((Bloc_particulier&)(*this)).operator==(a))   ) 
       return false;
     else  
      { if ((co_charge == a.co_charge) && (echelle == a.echelle)
           && (t_min == a.t_min )&& (t_max == a.t_max )&& (precedent == a.precedent )
           && (attribut == a.attribut) && (f_charge == a.f_charge)
           && (nom_fnD_t_min == a.nom_fnD_t_min) && (fnD_t_min == a.fnD_t_min)
           && (nom_fnD_t_max == a.nom_fnD_t_max) && (fnD_t_max == a.fnD_t_max)
           )
           return true;
        else
           return false;
       }    
    }
    /// @}  // end of group


/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

template <class Bloc_particulier>
BlocCharge<Bloc_particulier>& BlocCharge<Bloc_particulier>::operator
     = ( const BlocCharge<Bloc_particulier>& a) 
    { // tout d'abord la classe mère
//      ((Bloc_particulier)(*this)) = ((const Bloc_particulier&)(a));
//      ((Bloc_particulier)(*this)) = a ;
      ((Bloc_particulier&)(*this)).operator=(a);
      // puis les valeurs propres 
      co_charge = a.co_charge; echelle = a.echelle; t_min = a.t_min;
      t_max = a.t_max; precedent = a.precedent;attribut = a.attribut;
      f_charge = a.f_charge;
      nom_fnD_t_min = a.nom_fnD_t_min ; fnD_t_min = a.fnD_t_min;
      nom_fnD_t_max = a.nom_fnD_t_max ; fnD_t_max = a.fnD_t_max;
      return *this;
     }
     /// @}  // end of group

/// @addtogroup Groupe_concernant_le_chargement
///  @{
///
template <class Bloc_particulier>
bool BlocCharge<Bloc_particulier>::operator 
     != (const  BlocCharge<Bloc_particulier>& a) const
    { return !(*this == a);}
   /// @}  // end of group

   

/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

/// affichage et definition interactive des commandes
/// attrib : donne un attribut éventuel à afficher dans les choix
template <class Bloc_particulier>
void BlocCharge<Bloc_particulier>::Info_commande_BlocCharge
     (ostream & sort,string attrib)
{  //On va proposer un menu
   string rep=" ";
   co_charge="_";
   f_charge="_";
   echelle = ConstMath::trespetit;
   t_min = - ConstMath::trespetit;
   t_max =  ConstMath::tresgrand;
 
   while ((Minuscules(rep) != "f")&&(Minuscules(rep) != "0"))
      {
       try 
        { int nb_choix=5;//valeur par défaut
        cout 
           << "\n (0 ou f) (defaut)  (fin)               "
           << "\n (1)  utilisation d'une courbe de charge     "
           << "\n (2)  fonction nD de charge "
           << "\n (3)  echelle  "
           << "\n (4)  temps mini fixe "
           << "\n (5)  temps maxi fixe "
           << "\n (6)  temps mini via une fonction nD "
           << "\n (7)  temps maxi via une fonction nD";
        if (attrib != "_")
           {cout << "\n (8)  attribut: "<<attrib <<" ";
            nb_choix=8;
            };
        cout << "\n  ";
        // procédure de lecture avec prise en charge d'un retour chariot
        rep = lect_return_defaut(false,"f");
        if ((Minuscules(rep) == "f") || (Minuscules(rep) == "0"))// sortie
          {if (attribut != "_")
              sort << " ATTRIBUT_ "<<attribut << " ";
           if (co_charge != "_")
              sort << " COURBE_CHARGE: "<<co_charge<<" ";
           if (f_charge != "_")
              sort << " Fonction_nD_CHARGE: "<<f_charge<<" ";
           if (echelle != ConstMath::trespetit)
              sort << " ECHELLE: "<< echelle<<" ";
           if ((t_min != (- ConstMath::trespetit)) || (nom_fnD_t_min != ""))
             { sort << " TEMPS_MINI= ";
               if (nom_fnD_t_min == "")
                 {sort << t_min << " ";}
               else {sort << " fct_nD: " << nom_fnD_t_min << " ";};
             };
           if ((t_max != ConstMath::tresgrand) || (nom_fnD_t_max != ""))
             { sort << " TEMPS_MAXI= ";
               if (nom_fnD_t_max == "")
                 {sort << t_max << " ";}
               else {sort << " fct_nD: " << nom_fnD_t_max << " ";};
             };
           break;
          };
        int num = ChangeEntier(rep);
        bool choix_valide=false;
        if ((num >= 0)&&(num<=nb_choix))
             { choix_valide=true; }
        else { cout << "\n Erreur on attendait un entier entre 0 et "<<nb_choix<<" !!, "
                    << "\n redonnez une bonne valeur"
                    << "\n ou taper f ou 0 pour arreter le programme"; 
               choix_valide=false;
             }
        switch (num)
         { case 0:  // sortie
             { break;} // normalement cela a déjà été filtré avant
           case 1:  // courbe de charge
             { cout << "\n nom de la courbe de charge  ? ";
               co_charge=lect_chaine();cout << " nom lu = "<< co_charge;
               break;
              }
           case 2:  // fonction nD
             { cout << "\n nom de la fonction nD de charge ? ";
               f_charge=lect_chaine();cout << " nom lu = "<< f_charge;
               break;
              }
           case 3:  // l'echelle
             { cout << "\n valeur de l'echelle (un reel)  ? ";
               echelle=lect_double();cout << " valeur lue = "<< echelle;
               break;
              }
           case 4:  // temps mini fixe
              { cout << "\n valeur du temps mini fixe(un reel)  ? ";
                t_min=lect_double();cout << " valeur lue = "<< t_min;
                nom_fnD_t_min=""; // par précaution si plusieurs passes
                break;
              }
           case 5:  // temps maxi fixe
              { cout << "\n valeur du temps maxi fixe(un reel)  ? ";
                t_max=lect_double();cout << " valeur lue = "<< t_max;
                nom_fnD_t_max=""; // par précaution si plisieurs passes
                break;
              }
           case 6:  // temps mini via une fonction nD
              { cout << "\n nom fonction nD pour temps mini (un string)  ? ";
                nom_fnD_t_min=lect_chaine();cout << " valeur lue = "<< nom_fnD_t_min;
                break;
              }
           case 7:  // temps maxi via une fonction nD
              { cout << "\n nom fonction nD temps maxi (un string)  ? ";
                nom_fnD_t_max=lect_chaine();cout << " valeur lue = "<< nom_fnD_t_max;
                break;
              }
           case 8:  // attribut éventuel
              {cout << "\n ajout de l'attribut "<<attrib <<"  (rep o ou n (defaut))  ? ";
               string reponse="";
               reponse = lect_return_defaut(false,"n");
               cout << " valeur lue ="<< reponse;
               if (Minuscules(reponse) == "o") { attribut = attrib;}
               else                            { attribut = "_";};
               break;
              }
           default:
             cout << "\n le cas "<<rep<<" n'est pas  traite !!, bizarre, il faut se plaindre !! ";
          };
        }    
       catch (ErrSortieFinale)
            // cas d'une direction voulue vers la sortie
            // on relance l'interuption pour le niveau supérieur
          { ErrSortieFinale toto;
            throw (toto);
          }
       catch (...)//(UtilLecture::ErrNouvelleDonnee erreur)
        {  cout << "\n Erreur on attendait un des mots cles proposes !!, "
                << "\n redonnez une bonne valeur"
                << "\n ou taper f ou 0 pour sortir "; 
        };
      }; //-- fin du while

};
/// @}  // end of group



/// @addtogroup Groupe_concernant_le_chargement
///  @{
///

/// mise en place de l'association des fonctions nD, dont ensuite on garde un pointeur
/// en retour indique si l'association est ok
template <class Bloc_particulier>
bool BlocCharge<Bloc_particulier>::Mise_en_place_des_fonction_nD(const LesFonctions_nD& lesFonctionsnD)
{ bool retour = true;
  // on regarde et on récupère s'il le faut la fct nD associée avec la résultante du torseur
  if (nom_fnD_t_min.length())
    {fnD_t_min = lesFonctionsnD.Trouve(nom_fnD_t_min);
     if (fnD_t_min != NULL)
      {// on vérifie qu'en retour on a un scalaire
       if (fnD_t_min->NbComposante() != 1)
         {cout << "\n *** erreur dans  l'utilisation d'une fonction nD avec grandeur(s) globale(s)"
               << " cas du calcul du temps mini"
               << " en retour, le nombre de composante"<< fnD_t_min->NbComposante()
               << " est different de 1  "
               << endl;
          Sortie(1);
         };
      };
    };
  // on regarde et on récupère s'il le faut la fct nD associée avec la résultante du torseur
  if (nom_fnD_t_max.length())
    {fnD_t_max = lesFonctionsnD.Trouve(nom_fnD_t_max);
     if (fnD_t_max != NULL)
      {// on vérifie qu'en retour on a un scalaire
       if (fnD_t_max->NbComposante() != 1)
         {cout << "\n *** erreur dans  l'utilisation d'une fonction nD avec grandeur(s) globale(s)"
               << " cas du calcul du temps maxi"
               << " en retour, le nombre de composante"<< fnD_t_max->NbComposante()
               << " est different de 1  "
               << endl;
          Sortie(1);
         };
      };
    };
  // puis on appelle la fonction membre identique
  retour = retour && Bloc_particulier::Mise_en_place_des_fonction_nD(lesFonctionsnD);
 
  return retour;
};
/// @}  // end of group


   
   
   
#endif  
