#ifndef __Bean_hxx__
#define __Bean_hxx__

#include <utility>
#include <deque>
#include <queue>
#include <functional>
#include "CRand.hxx"

typedef pair<int,double>  PaireBean;
typedef deque<PaireBean>  ChromoBean;
typedef deque<ChromoBean> TGenome;

// Classes utilitaires permettant de trier des paires dans l'ordre decroissant 
// la premiere classe trie selon le membre first
// la seconde classe trie selon le membre second

template <class Paire>
class TriPaireFirst
{
  public:
    bool operator()(const Paire &a, const Paire &b)
    {
      return a.first > b.first;
    }
};

template <class Paire>
class TriPaireSecond
{
  public:
    bool operator()(const Paire &a, const Paire &b)
    {
      return a.second > b.second;
    }
};

class ostream;
ostream &operator<<(ostream &a,const PaireBean &b);
ostream &operator<<(ostream &a,const ChromoBean &b);
ostream &operator<<(ostream &a,const TGenome &b);

class Bean
{
  private:
    static CRand Generateur;
  public:
    static void ResetGenerateur(int);
    template <class iterateur>
    static void Encode(iterateur a, iterateur b,ChromoBean &c);
    template <class iterateur>
    static void Decode(ChromoBean &a,iterateur c);
};


typedef priority_queue<double,deque<double>,greater<double> > TPQDouble;
typedef priority_queue<PaireBean,deque<PaireBean>,TriPaireFirst<PaireBean> > TPQBeanVilles;
typedef priority_queue<PaireBean,deque<PaireBean>,TriPaireSecond<PaireBean> > TPQBeanClefs;


template <class iterateur>
void Bean::Decode(ChromoBean &a,iterateur c)
{
  TPQBeanClefs pqc;
  ChromoBean::iterator debut=a.begin();
  ChromoBean::iterator fin=a.end();

  while(debut!=fin)
  {
    pqc.push(*debut);
    debut++;
  }

  while (!pqc.empty())
  {
    *c=pqc.top().first;
    pqc.pop();
    c++;
  }

}

template <class iterateur>
void Bean::Encode(iterateur a, iterateur b,ChromoBean &c)
{
  TPQDouble     doubles;
  TPQBeanVilles pqf;
  iterateur     z(a);

  while (z!=b)
  {
    doubles.push(Generateur());
    z++;
  }

  z=a;
  while (z!=b)
  {
    pqf.push(make_pair(*z,doubles.top()));
    z++;
    doubles.pop();
  }

  c.resize(0);

  while (!pqf.empty())
  {
    c.push_back(pqf.top());
    pqf.pop();
  }
}



#endif
