// 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-2021 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/>.

#include "Temps_CPU_HZpp.h"


// ----- définition des variables statiques  ------------

short int Temps_CPU_HZpp::impre_schem_XML=0;

// CONSTRUCTEURS :
//  par défaut on initialise à défaut
Temps_CPU_HZpp::Temps_CPU_HZpp():
  temps_user(0),debut_temps_user(0),comptage_en_cours(false)
    {};

// mise en route du comptage
void Temps_CPU_HZpp::Mise_en_route_du_comptage()
  {
#ifdef  UTILISATION_DE_LA_LIBRAIRIE_BOOST
     if (!comptage_en_cours)
     { comptage_en_cours = true;
       // on récup le temps depuis le début : c'est la seule qui marche pour le cumul
//high_resolution_clock
       // -- pour le temps user
//     boost::chrono::process_user_cpu_clock::duration tuti_1
//           = boost::chrono::process_user_cpu_clock::now().time_since_epoch();
       boost::chrono::high_resolution_clock::duration tuti_1
           = boost::chrono::high_resolution_clock::now().time_since_epoch();
       // on transforme en microseconde
//     debut_temps_user = boost::chrono::duration_cast<boost::chrono::microseconds>(tuti_1);
       debut_temps_user = boost::chrono::duration_cast<boost::chrono::nanoseconds>(tuti_1);
     };
#endif
  };

// arrêt du comptage et cumul
void Temps_CPU_HZpp::Arret_du_comptage()
  {  // comptage
#ifdef  UTILISATION_DE_LA_LIBRAIRIE_BOOST
     if (comptage_en_cours)
     { comptage_en_cours = false;
       // on récup le temps en nano depuis le début
   
       // -- pour le temps user
//     boost::chrono::process_user_cpu_clock::duration tuti_1
//           = boost::chrono::process_user_cpu_clock::now().time_since_epoch();
       boost::chrono::high_resolution_clock::duration tuti_1
           = boost::chrono::high_resolution_clock::now().time_since_epoch();
       // on transforme en microseconde et on incrémente
//     temps_user += boost::chrono::duration_cast<boost::chrono::microseconds>(tuti_1) - debut_temps_user;
       temps_user += boost::chrono::duration_cast<boost::chrono::nanoseconds>(tuti_1) - debut_temps_user;
     };

#endif
  };

// affichage
// si niveau = 1 ou plus, on a plus d'info pour le débug par exemple
void Temps_CPU_HZpp::Affiche(ostream & sort,int niveau)
 { // on arrondi en ms
#ifdef  UTILISATION_DE_LA_LIBRAIRIE_BOOST
  
//   sort << " tps(mls)_user:" << temps_user.count()/1000;
   sort << " tps(mls)_user:" << temps_user.count()/1000000;
   if (niveau > 0)
     { sort << "\n temps_user:" << temps_user;
       sort << "\n deb_t_user:" << debut_temps_user
            << endl;
     };
#endif
 };

// affichage en hh:mn:s:ml
void Temps_CPU_HZpp::Affiche_hh_mn_s_ml(ostream & sort)
 {
#ifdef  UTILISATION_DE_LA_LIBRAIRIE_BOOST
//   // on essaie d'utiliser les conversions
//   sort << "\n temps_user:"
//        << round<hours>(temps_user) << ":"
//        << round<minutes>(temps_user) << ":"
//        << round<seconds>(temps_user) << ":"
//        << round<milliseconds>(temps_user) ;
//   sort << "\n temps_system:"
//        << round<hours>(temps_system) << ":"
//        << round<minutes>(temps_system) << ":"
//        << round<seconds>(temps_system) << ":"
//        << round<milliseconds>(temps_system);
//   sort << "\n temps_reel:"
//        << round<hours>(temps_reel) << ":"
//        << round<minutes>(temps_reel) << ":"
//        << round<seconds>(temps_reel) << ":"
//        << round<milliseconds>(temps_reel)
//        << endl;

// autre solution utilisant le template de boost
//display(cout, -boost::chrono::milliseconds(6)) << '\n';
sort << "\n temps_user:";
display(cout, temps_user) << '\n';
  
#endif
 };

 // surcharge de l'operator de lecture
istream & operator >> (istream & ent, Temps_CPU_HZpp & a)
 { string toto;
   long long u1;//,u2,u3; // variable intermédiaires
   ent >> toto >> u1;// >> toto >> u2 >> toto >> u3;

//   microseconds truc_user(u1);
   boost::chrono::nanoseconds truc_user(u1);
  
   a.temps_user = truc_user;
  
   return ent;
  };
  
 // surcharge de l'operator d'ecriture
ostream & operator << (ostream & sort , const Temps_CPU_HZpp & a)
 {
//  sort << "\n temps_user:" << a.temps_user
//        << " temps_reel:" << a.temps_reel
//        << " temps_system:" << a.temps_system
//        << endl;
   sort << " U= " << a.temps_user.count();
//   cout << " U= " << a.temps_user.count()
//        << " S= " << a.temps_system.count()
//        << " R= " << a.temps_reel.count();
//  double toto = a.temps_reel.count();
//  cout << "\n toto= "<< toto <<endl;
  
   return sort;
  };


// sortie du schemaXML: en fonction de enu  
void Temps_CPU_HZpp::SchemaXML_Temps_CPU_HZpp(ofstream& sort,const Enum_IO_XML enu) const
 {// sortie balisée simple  
  switch (enu)
  {case XML_TYPE_GLOBAUX: 
     {sort << "\n <!--  *******************************************************  -->"
           << "\n<xs:complexType name=\"Temps_CPU_HZpp\" >"
           << "\n    <xs:annotation>"
           << "\n      <xs:documentation> type simple pour definir un temps cpu  </xs:documentation>"
           << "\n    </xs:annotation>"
           << "\n    <xs:attribute  name=\"temps_user\" type=\"xs:long\" use=\"required\" />"
           << "\n    <xs:attribute  name=\"temps_reel\" type=\"xs:long\" use=\"required\" />"
           << "\n    <xs:attribute  name=\"temps_system\" type=\"xs:long\" use=\"required\" />"
           << "\n</xs:complexType>";
       Temps_CPU_HZpp::impre_schem_XML=1; // une seule sortie
      };
   default:
    cout << "\n Temps_CPU_HZpp::SchemaXML_Temps_CPU_HZpp: le cas "<<Nom_Enum_IO_XML(enu)
         << " n'est pas pris en compte actuellement ! "<< endl;
  };
 };

// surcharge de lecture en XML
istream & Temps_CPU_HZpp::LectXML_Temps_CPU_HZpp(istream & ent)
     { string nom;
       ent >> nom >> nom >> temps_user  >> nom ;
       return ent;
     };

    // surcharge d'ecriture en XML
ostream & Temps_CPU_HZpp::EcritXML_Temps_CPU_HZpp(ostream & sort)
     { sort << "<Temps_CPU_HZpp> temps_user= "<< temps_user
            << "</Temps_CPU_HZpp>";
       return sort;
     };


