#include <cstdio>
#include "ps_output.h"

#ifdef _USE_NAMESPACES
    namespace Else { 
#endif // _USE_NAMESPACES

// Dangerous tranf. are marked by '@@'


PsOutput::PsOutput(const string& filename, 
                   const string& graph_title,
                   const string& message,
                   const Real& originX,
                   const Real& originY,
                   const Real& scale_length) 
{
  //log file
  ps_file = new ofstream(filename.c_str());
  if (!ps_file)
  { 
    cerr << "Error opening file " << filename << endl;
    exit(1);
  }
  (*ps_file).precision(3);

  // arguments definitions
  title = graph_title;
  subtitle = message;

  scaleX0 = originX;
  scaleY0 = originY;
  scalelength = scale_length;
  
  // internal definitions
  scale_name = "scale_size";
  line_space = 20;
  info_pos_y = 200.0;
  system_char = 'A';

  // print the postscript header
  (*ps_file) << "%!" << endl
             << "%%Title: Evaluation result\n"
             << "%%Project: ELSE EVAL\n\n";

  // set the landscape mode 
  // warning all coordinate depends on this mode
  (*ps_file) << "90 rotate\n"
             << "-1 -1 scale\n"
             << "1 setlinewidth\n";
}

PsOutput::~PsOutput()
{
  // add the final poscript instruction
  (*ps_file) << "showpage" << endl;
  (*ps_file).close();
  delete(ps_file);
}

void 
PsOutput::setscale(const string& name, const Real& scale_length) 
{
  (*ps_file) << "/" << name << " {-" << scale_length << " mul} def\n";
}

void
PsOutput::set_current_color(const Real& color) 
{
  (*ps_file) << color << " setgray\n";
}

void
PsOutput::setposition(const Real& x, const Real& y) 
{
  (*ps_file) << x << " " << y <<" moveto\n\n";
}

void 
PsOutput::drawtitle(const Real& y, const Real& size) 
{
  Real char_cm_size = 0.68;
  Real page_cm_size = 29.0;
  VeryLongNatural page_pts_size = 800;
  Real posx = page_pts_size/2 - ((title.length()*char_cm_size*page_pts_size)/page_cm_size)/2;
  (*ps_file) << "%%DRAW THE TITLE " << title << endl
             << "gsave\n"
             << "   " << "0 setgray\n"
             << "   " << "2 setlinewidth\n"
             << "   /Helvetica findfont\n"
             << "   -" << size << " scalefont\n"
             << "   setfont\n"
             << "   newpath\n"
    // set the position and draw the title
             << "   -" << posx << " " << y << " moveto (" << title // upper(title)
             << ") show\n"
             << "grestore\n\n";

}

void
PsOutput::drawsubtitle(const Real& y, const Real& size) 
{
  Real char_cm_size = 0.32;
  Real page_cm_size = 29.0;
  VeryLongNatural page_pts_size = 800;
  Real posx = page_pts_size/2 - ((subtitle.length()*char_cm_size*page_pts_size)/page_cm_size)/2;
  (*ps_file) << "%%DRAW THE SUBTITLE " << subtitle << endl
             << "gsave\n"
             << "   " << "0 setgray\n"
             << "   " << "2 setlinewidth\n"
             << "   /Helvetica findfont\n"
             << "   -" << size << " scalefont\n"
             << "   setfont\n"
             << "   newpath\n"
    // set the position and draw the subtitle
             << "   -" << posx << " " << y << " moveto (" << subtitle
             << ") show\n"
             << "grestore\n\n";

}

void
PsOutput::drawarrow(const Real& x1, const Real& y1,
                    const Real& x2, const Real& y2,
                    const Real& x3, const Real& y3)
{
  (*ps_file) << "%%DRAW AN ARROW\n"
             << "gsave\n"
             << "   " << "newpath\n"
             << "   " << -scaleX0 << " " << scaleY0 <<" moveto\n"
    // set the first point
             << "   " << x1 << " " << scale_name << " " 
             << "   " << y1 << " " << scale_name << " rmoveto\n"
    // draw the first line
             << "   " << x2 << " " << scale_name << " " << -scaleX0 << " add " 
             << y2  << " " << scale_name << " " << scaleY0 << " add "
             << " lineto\n"
    // draw the second line
             << "   " << x3 << " " << scale_name << " " << -scaleX0 << " add " 
             << y3  << " " << scale_name << " " << scaleY0 << " add "
             << " lineto\n"
             << "   " << "closepath\n" 
    // fill the arrow
             << "   " << "fill\n"
             << "grestore\n\n";
}

void
PsOutput::drawline(const Real& from_x, const Real& from_y,
                   const Real& delta_x, const Real& delta_y) 
{
  (*ps_file) << "%%DRAW A LINE\n"
             << "   " << "newpath\n"
             << "       " << -scaleX0 << " " << scaleY0 <<" moveto\n"
    // set the from_point
             << "       " << from_x << " " << scale_name << " " 
             << "       " << from_y << " " << scale_name << " rmoveto\n"
    // set the line with the delta value
             << "       " << delta_x << " " << scale_name <<" " 
             << delta_y << " " << scale_name <<" " << "rlineto\n"
             << "   " << "closepath\n"
    // draw
             << "   " << "stroke\n";
        
}

void
PsOutput::drawgrid(const VeryLongNatural& line_number, const bool with_segment, const bool vertical_only) 
{
  (*ps_file) << "%%DRAW THE GRID\n";
  if (!line_number == 0)
  {    
    set_current_color(0.9);
    Real current_coord; // the temp coordinate to draw lines
        
    // draw the background grid
    for (VeryLongNatural i = 0; i <= line_number; i++)
    {
      current_coord = i*(1.0/(Real)line_number);
      if (!vertical_only) drawline(0.0,current_coord,1.0,0.0); // draw the horizontal lines
      drawline(current_coord,0.0,0.0,1.0); // draw the vertical lines
    }
    set_current_color(0.0);
    if (with_segment)
    {
      // draw the little segment
      Real segment_length = 0.01;
      current_coord = 0.0;
      for (VeryLongNatural i = 1; i < line_number/2; i++) 
      {    
        current_coord += (1.0/(Real)line_number);
        drawsegment(-segment_length, current_coord,segment_length, current_coord);
        drawsegment(current_coord, -segment_length, current_coord , segment_length);
      }
      segment_length = 0.02;
      current_coord += (1.0/(Real)line_number);
      drawsegment(-segment_length, current_coord,segment_length, current_coord);      
      drawsegment(current_coord, -segment_length, current_coord , segment_length);

      segment_length = 0.01;
      for (VeryLongNatural i = (line_number/2) +1; i < line_number; i++) {
        current_coord += (1.0/(Real)line_number);
        drawsegment(-segment_length, current_coord,segment_length, current_coord);      
        drawsegment(current_coord, -segment_length, current_coord , segment_length);
      }
    }
  }
}

void
PsOutput::draw_line_grid(const VeryLongNatural& line_number) 
{
  if (!line_number == 0)
  {    
    Real current_coord; // the temp coordinate to draw lines
    set_current_color(0.0);

    // draw the first big segment
    Real segment_length = 0.02;
    current_coord = 0.0;
    drawsegment(current_coord, -segment_length, current_coord , segment_length);

    // draw the little segments
    segment_length = 0.01;
    for (VeryLongNatural i = 1; i < line_number/2; i++)
    {
      current_coord += (1.0/(Real)line_number);
      drawsegment(current_coord, -segment_length, current_coord , segment_length);
    }

    // draw the middle big segment
    segment_length = 0.02;
    current_coord += (1.0/(Real)line_number);
    drawsegment(current_coord, -segment_length, current_coord , segment_length);
        
    // draw the little segments    
    segment_length = 0.01;
    for (VeryLongNatural i = (line_number/2) +1; i < line_number; i++)
    {
      current_coord += (1.0/(Real)line_number);
      drawsegment(current_coord, -segment_length, current_coord , segment_length);
    }
        
    // PUT THE LABEL
    VeryLongNatural buffer_length = 12;     // to convert Real to string
    char buffer[buffer_length]; // to convert Real to string
    for (VeryLongNatural i = 0; i < line_number; i++)
    {
      //drawsegment(current_coord, -segment_length, current_coord , segment_length);
      sprintf(buffer,"%.2f",current_coord);
      string label = buffer;
      drawlabel(current_coord-0.015,-segment_length-0.03, label, 8.0);
      current_coord -= (1.0/(Real)line_number);
    }

  }
}

void
PsOutput::drawsegment(const Real& from_x, const Real& from_y,
                      const Real& to_x,   const Real& to_y) 
{
  (*ps_file) << "%%DRAW A SEGMENT\n"
             << "gsave\n"
    //     << "   " << "1 setlinewidth\n"
             << "   " << "newpath\n"
             << "   " << -scaleX0 << " " << scaleY0 << " moveto\n"
    // set the from-point
             << "   " << from_x << " " << scale_name << " " 
             << "   " << from_y << " " << scale_name << " rmoveto\n"
    // set the to-point
             << "   " << to_x << " " << scale_name << " " << scaleX0 << " sub "
             << to_y  << " " << scale_name << " " << scaleY0 << " add "
             << " lineto\n"
             << "   " << "closepath\n"
    // draw
             << "   " << "stroke\n"
             << "grestore\n\n";
}

void
PsOutput::drawbox(const Real& from_x,  const Real& from_y,
                  const Real& delta_x, const Real& delta_y) 
{
  (*ps_file) << "%%DRAW A BOX\n"
             << "gsave\n"
             << "   " << "1 setlinewidth\n"
    //begin "drawing"
             << "   " << "newpath\n"
             << "   " << -scaleX0 << " " << scaleY0 << " moveto\n"
    //set position of the left corner
             << "   " << from_x << " " << scale_name << " " 
             << "   " << from_y << " " << scale_name << " rmoveto\n"
    //draw the four lines
             << "   " << delta_x << " " << scale_name << " "
             << 0 << " rlineto\n"
             << "   " << 0 << " "
             << delta_y  << " " << scale_name << " "
             << " rlineto\n"
             << "   " << -delta_x << " " << scale_name << " "
             << 0 
             << " rlineto\n"
             << "   " << 0 << " "
             << -delta_y  << " " << scale_name << " "
             << " rlineto\n"
             << "   " << "closepath\n"
    //finish drawing
             << "   " << "stroke\n"
             << "grestore\n\n";
}

void PsOutput::drawlabel(const Real& x, const Real& y, const string& text,
                         const Real& text_size, const Real& width) 
{
 (*ps_file) << "%%DRAW LABEL " << text << endl
             << "gsave\n"
    // set the drawing width and the text size
             << "   " << width << " setlinewidth\n"
             << "   /Helvetica findfont\n"
             << "   -" << text_size << " scalefont\n"
             << "   setfont\n"
             << "   newpath\n"
             << "   " << -scaleX0 << " " << scaleY0 <<" moveto\n"
    // set the position to the left corner of the text
             << "   " << x << " " << scale_name << " " 
             << "   " << y << " " << scale_name 
    // write the text
             << " rmoveto (" << text << ") show\n"
             << "grestore\n\n";

}

void
PsOutput::drawtext(const Real& x, const Real& y,
                   const string& text, const Real& text_size, const Real& width) 
{
  (*ps_file) << "%%DRAW TEXT " << endl
             << "gsave\n"
             << "   " << width << " setlinewidth\n"
             << "   /Helvetica findfont\n"
             << "   -" << text_size << " scalefont\n"
             << "   setfont\n"
             << "   newpath\n"
             << "   " << -x << " " << y 
             << " moveto (" << text << ") show\n"
             << "grestore\n\n";
}


void
PsOutput::triangle_print(const Real& P, const Real& D, 
                         const Real& Pmin,  const Real& Pmoy,
                         const Real& Pmax,  const VeryLongNatural& NbrCase) 
{
  // graph environnement variable    
  set_current_color(0.0);
    
  // the different label
  string PD_label = "(P,D)";
  string Pmin_label = "Pmin";
  string Pmoy_label = "Pmoy";
  string Pmax_label = "Pmax";

  string origin_label = "(0,0)";
  string P_label = "P (1,0)";
  string D_label = "D (0,1)";
 
  // graph important point
  drawtitle(scaleY0-scalelength-100);
  drawsubtitle();

  setscale(scale_name, scalelength);

  // DRAW THE SCALE
  // draw the grid
  drawgrid(10);
  // Ox axe
  drawline(0.0,0.0,1.0,0.0);
  drawarrow(1.0,0.0,0.98,0.01,0.98,-0.01);
  // Oy axe
  drawline(0.0,0.0,0.0,1.0);
  drawarrow(0.0,1.0,0.01,0.98,-0.01, 0.98);

                        
  // PUT THE SCALE LABEL
  drawlabel(-0.03, -0.03, origin_label, 10.0);
  drawlabel(1, -0.03, P_label, 10.0);
  drawlabel(-0.08, 1.01, D_label, 10.0);
 
  // DRAW THE TRIANGLE
  setposition(scaleX0,scaleY0);
 
  drawsegment(P,D,Pmin,1.0);
  drawsegment(Pmin,1.0,Pmax,1.0); 
  drawsegment(Pmax,1.0,P,D);
  drawsegment(P,D,Pmoy,1.0);

  // PUT THE POINT LABEL
  drawlabel(P, D-0.02, PD_label, 10.0);
  drawlabel(Pmin-0.06, 0.98, Pmin_label, 10.0);
  drawlabel(Pmoy-0.02, 1.01, Pmoy_label, 10.0);
  drawlabel(Pmax+0.01, 0.98, Pmax_label, 10.0);

  // GIVE DESCRIPTION
  VeryLongNatural buffer_length = 12;
  char buffer[buffer_length];

    // for the P value
  sprintf(buffer,"%.3f",P);
  drawtext(scaleX0+scalelength+50.0,scaleY0-380,"P", 12.0);
  drawtext(scaleX0+scalelength+90.0,scaleY0-380,"(Precision)", 12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-380," = " + string(buffer), 12.0);

  // for the D value
  sprintf(buffer,"%.3f",D);
  drawtext(scaleX0+scalelength+50.0,scaleY0-360,"D",12.0);
  drawtext(scaleX0+scalelength+90.0,scaleY0-360,"(Decision)", 12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-360," = " + string(buffer), 12.0);

  // for the Pmin value
  sprintf(buffer,"%.3f",Pmin);
  drawtext(scaleX0+scalelength+50.0,scaleY0-340,Pmin_label,12.0);
  drawtext(scaleX0+scalelength+90.0,scaleY0-340,"(P lower bound)", 12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-340," = " + string(buffer), 12.0);

  // for the Pmoy value
  sprintf(buffer,"%.3f",Pmoy);
  drawtext(scaleX0+scalelength+50.0,scaleY0-320,Pmoy_label,12.0);
  drawtext(scaleX0+scalelength+90.0,scaleY0-320,"(P average)", 12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-320," = " + string(buffer), 12.0);

  // for the Pmax value
  sprintf(buffer,"%.3f",Pmax);
  string Pmax_value    = "Pmax (P upper bound)        = " + string(buffer);
  drawtext(scaleX0+scalelength+50.0,scaleY0-300,Pmax_label,12.0);
  drawtext(scaleX0+scalelength+90.0,scaleY0-300,"(P upper bound)", 12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-300," = " + string(buffer), 12.0);

  // gives the number of evaluated case    
  sprintf(buffer,"%d",NbrCase);
  drawtext(scaleX0+scalelength+50.0,scaleY0-280,"Number of evaluated case",12.0);
  drawtext(scaleX0+scalelength+200.0,scaleY0-280," = " + string(buffer), 12.0);
    
}

void
PsOutput::triangles_print(const VeryLongNatural& number_triangle)
{
  set_current_color(0.0);

  // set the label
  string origin_label = "(0,0)";
  string P_label = "P (1,0)";
  string D_label = "D (0,1)";
  
  drawtitle();
  drawsubtitle(80.0);
  setscale(scale_name, scalelength);

  line_space = scalelength / (Real) number_triangle;
  info_pos_y = 165.0;

  // draw the grid
  drawgrid(10);

  // DRAW THE SCALE
  drawline(0.0,0.0,1.0,0.0);
  drawarrow(1.0,0.0,0.98,0.01,0.98,-0.01);
  drawline(0.0,0.0,0.0,1.0);
  drawarrow(0.0,1.0,0.01,0.98,-0.01, 0.98);
            
  // PUT THE SCALE LABEL
  drawlabel(-0.03, -0.03, origin_label, 10.0);
  drawlabel(1, -0.03, P_label, 10.0);
  drawlabel(-0.08, 1.01, D_label, 10.0);

  // DRAW INSCRIPTION
  drawlabel(1.05,1.05," LETTER = SYSTEM_NAME : P_score D_score (number of evaluated case)", 10);
}


void 
PsOutput::add_triangle(const Real& P, const Real& D, 
                       const Real& Pmin, const Real& Pmax, const VeryLongNatural& NbrCase,
                       const Real& color, const string& name) 
{
  // set the different label
  string Pmin_label = "Pmin";
  string Pmoy_label = "Pmoy";
  string Pmax_label = "Pmax";
  string cut_name = name;
  if (cut_name.length()>10)
    cut_name = cut_name.substr(0,10);  // @@ POssible bug, orig: cut_name.at(0,10)
    
  set_current_color(color);
    
  // DRAW THE TRIANGLE
  setposition(scaleX0,scaleY0);
  drawsegment(P, D, Pmin, 1.0);
  drawsegment(Pmin, 1.0, Pmax, 1.0);
  drawsegment(Pmax, 1.0, P,D);
    
  // PUT THE SYSTEM NAME
  drawlabel(P, D-0.02, string(1,system_char), 10.0);
    
  set_current_color(0.0);

  // GIVE DESCRIPTION
  VeryLongNatural buffer_length = 30;
  char buffer[buffer_length];
  string system_score(1,system_char);
  sprintf(buffer,": P = %.3f   D = %.3f   (%d)",P,D, NbrCase);
  system_score = system_score + " = " + cut_name;
  drawtext(scaleX0 + scalelength + 30.0,info_pos_y,system_score, 12.0);
  drawtext(scaleX0 + scalelength + 115.0,info_pos_y,buffer, 12.0);
  info_pos_y += line_space;

  system_char++;
}


void
PsOutput::add_point(const Real& P, const Real& D,
                    const VeryLongNatural& NbrCase, const string& name)
{
  Real char_half_size = 0.008; // for 10 points char
  string cut_name = name;
  if (cut_name.length()>10)
    cut_name = cut_name.substr(0,10);  // @@ at(0,10)

    // DRAW THE TRIANGLE
  setposition(scaleX0,scaleY0);
        
  // PUT THE SYSTEM NAME
  drawlabel(P-char_half_size, D-char_half_size, string(1,system_char), 10.0);

  // GIVE DESCRIPTION
  VeryLongNatural buffer_length = 30;
  char buffer[buffer_length];
  string system_score(1,system_char);
  sprintf(buffer,": P = %.3f   D = %.3f   (%d)",P,D, NbrCase);
  system_score = system_score + " = " + cut_name;
  drawtext(scaleX0 + scalelength + 30.0,info_pos_y,system_score, 12.0);
  drawtext(scaleX0 + scalelength + 115.0,info_pos_y,buffer, 12.0);
  info_pos_y += line_space;

  system_char++;
}


void
PsOutput::box_print(const Real& minPmin, const Real& minMoyP, const Real& Pmoy, 
                    const Real& maxMoyP, const Real& maxPmax, const VeryLongNatural& NbrCase) 
{
  // graph environnement variable
  Real y_position = 0.05;// distance between the scale and the box 
  Real box_width = 0.02; // width of the box
  string scale_name = "scale_size";
  scaleX0 = 400.0 - scalelength/2.0;
  set_current_color(0.0);

  // graph important point
  drawtitle(scaleY0-200);
  drawsubtitle();

  setscale(scale_name, scalelength);

  // DRAW THE SCALE
  draw_line_grid(10);
  drawline(0.0,0.0,1.0,0.0);
  drawarrow(1.0,0.0,0.98,0.01,0.98,-0.01);
 
                            
  // PUT THE SCALE LABEL
  drawlabel(1, -0.03, "P = 1.0" , 10.0);
     
  // DRAW THE BOX
  setposition(scaleX0,scaleY0); 
  drawsegment(minPmin, y_position , minMoyP , y_position);
  drawsegment(maxMoyP, y_position , maxPmax , y_position);
  drawbox(minMoyP,y_position-(box_width/2), (Pmoy-minMoyP), box_width);
  drawbox(Pmoy,y_position-(box_width/2),(maxMoyP-Pmoy), box_width);

  // DRAW THE BRACKET
  // the first one
  drawsegment(minPmin+0.005, y_position-(box_width/2) , 
              minPmin , y_position-(box_width/2));
  drawsegment(minPmin, y_position-(box_width/2) , 
              minPmin , y_position+(box_width/2));
  drawsegment(minPmin, y_position+(box_width/2) , 
              minPmin+0.005, y_position+(box_width/2));
  // the second one
  drawsegment(maxPmax-0.005, y_position-(box_width/2) , 
              maxPmax , y_position-(box_width/2));
  drawsegment(maxPmax, y_position-(box_width/2) , 
              maxPmax , y_position+(box_width/2));
  drawsegment(maxPmax, y_position+(box_width/2) , 
              maxPmax-0.005, y_position+(box_width/2));

 
  // PUT THE POINT LABEL
  drawlabel(minPmin-0.04, y_position - 0.03, "min Pmin" , 10.0);
  drawlabel(minMoyP-0.07, y_position + 0.02, "min Pmoy" , 10.0);
  drawlabel(maxMoyP+0.01, y_position + 0.02, "max Pmoy" , 10.0);
  drawlabel(maxPmax-0.04, y_position - 0.03, "max Pmax" , 10.0);

    // GIVE DESCRIPTION
  VeryLongNatural buffer_length = 12;
  char buffer[buffer_length];

  // for the minPmin value
  sprintf(buffer,"%.3f",minPmin);
  drawtext(scaleX0,scaleY0+160,"minPmin", 12.0);
  drawtext(scaleX0+70,scaleY0+160, " = " + string(buffer) , 12.0);
  drawtext(scaleX0+120,scaleY0+160, 
           "an evaluation of the minimum of Pmin (read formula in documentation)", 12.0);

  // for the minPmoy value
  sprintf(buffer,"%.3f",minMoyP);
  string minPmoy_value = "minPmoy = " + 
    string(buffer);
  drawtext(scaleX0,scaleY0+180,"minPmoy", 12.0);
  drawtext(scaleX0+70,scaleY0+180, " = " + string(buffer) , 12.0);
  drawtext(scaleX0+120,scaleY0+180, 
           "an evaluation of the minimum of the average of P (read formula in documentation)", 12.0);

  // for the Pmoy value
  sprintf(buffer,"%.3f",Pmoy);
  string Pmoy_value = "Pmoy = " + 
    string(buffer);
  drawtext(scaleX0,scaleY0+200,"Pmoy", 12.0);
  drawtext(scaleX0+70,scaleY0+200, " = " + string(buffer) , 12.0);
  drawtext(scaleX0+120,scaleY0+200, 
           "the average of P (read formula in documentation)", 12.0);

  // for the maxPmoy value
  sprintf(buffer,"%.3f",maxMoyP);
  drawtext(scaleX0,scaleY0+220,"maxPmoy", 12.0);
  drawtext(scaleX0+70,scaleY0+220, " = " + string(buffer) , 12.0);
  drawtext(scaleX0+120,scaleY0+220, 
           "an evaluation of the maximum of the average of P (read formula in documentation)", 12.0);


  // for the maxPmaxvalue
  sprintf(buffer,"%.3f",maxPmax);
  drawtext(scaleX0,scaleY0+240, "maxPmax", 12.0);
  drawtext(scaleX0+70,scaleY0+240, " = " + string(buffer) , 12.0);
  drawtext(scaleX0+120,scaleY0+240, 
           "an evaluation of the maximum of Pmax (read formula in documentation)", 12.0);

  // the number of evaluated case
  sprintf(buffer,"%d",NbrCase);
  string NbrCase_value = "Number of evaluated cases = " + 
    string(buffer);
  drawtext(scaleX0,scaleY0+260, NbrCase_value, 12.0);

}


void
PsOutput::boxes_print(const VeryLongNatural& number_boxes) 
{
  // graph important point
  drawtitle();
  drawsubtitle();

  setscale(scale_name, scalelength);
  set_current_color(0.0);

  // DRAW THE SCALE
  drawline(0.0,0.0,1.0,0.0);
  drawarrow(1.0,0.0,0.98,0.01,0.98,-0.01);
                            
  // PUT THE SCALE LABEL
  drawtext(-0.03, -0.03, "P = 0.0" , 10.0);
  drawtext(1, -0.03, "P = 1.0" , 10.0);

  // draw a background grid
  drawgrid(10,false,true);

  // put the little segment on the scale
  draw_line_grid(10);

  // initialise the position of descriptions for each system
  // the spaces between each line
  // and the first line position
  line_space = scalelength / ((Real) number_boxes + 1);
  info_pos_y = 170.0;

  // ************
  // PUT A LEGEND
  Real centering_legend = 0.5;
  Real minPmin =  centering_legend + 0.0;
  Real minMoyP = centering_legend + 0.2;
  Real Pmoy = centering_legend + 0.4;
  Real maxMoyP = centering_legend + 0.6;
  Real maxPmax = centering_legend + 0.7;
  Real y_position = 1.1;
  Real box_width = 0.04;                                            
  
  // DRAW THE BOX
  drawsegment(minPmin, y_position , minMoyP , y_position);
  drawsegment(maxMoyP, y_position , maxPmax , y_position);
  drawbox(minMoyP,y_position-(box_width/2), (Pmoy-minMoyP), box_width);
  drawbox(Pmoy,y_position-(box_width/2),(maxMoyP-Pmoy), box_width);

  // DRAW THE BRACKET
  // the first one
  drawsegment(minPmin+0.01, y_position-(box_width/2) , 
              minPmin , y_position-(box_width/2));
  drawsegment(minPmin, y_position-(box_width/2) , 
              minPmin , y_position+(box_width/2));
  drawsegment(minPmin, y_position+(box_width/2) , 
              minPmin+0.01, y_position+(box_width/2));
  // the second one
  drawsegment(maxPmax-0.01, y_position-(box_width/2) , 
              maxPmax , y_position-(box_width/2));
  drawsegment(maxPmax, y_position-(box_width/2) , 
              maxPmax , y_position+(box_width/2));
  drawsegment(maxPmax, y_position+(box_width/2) , 
              maxPmax-0.01, y_position+(box_width/2));

  // draw the label on inscription
  drawlabel(minPmin-box_width, y_position + box_width, "min Pmin" , 10.0);
  drawlabel(minMoyP-box_width, y_position + box_width, "min Pmoy" , 10.0);
  drawlabel(Pmoy-0.02, y_position + box_width, "Pmoy" , 10.0);
  drawlabel(maxMoyP-0.1, y_position + box_width, "max Pmoy" , 10.0);    
  drawlabel(maxPmax-0.04, y_position + box_width, "max Pmax" , 10.0);

  // draw inscription
  drawlabel(1.03, 1.02,"SYSTEM_NAME: ", 10);
  drawlabel(1.25,1.02,"maxPmin minPmoy Pmoy", 10);
  drawlabel(1.25,0.98,"maxPmoy maxPmax (number of evaluated cases)", 10);
}


void 
PsOutput::add_box(const Real& minPmin, const Real& minMoyP,
                  const Real& Pmoy,    const Real& maxMoyP, 
                  const Real& maxPmax, const VeryLongNatural& NbrCase,
                  const Real& y_position, const string& name) 
{
  Real box_width = 0.02;
  string cut_name = name;
  if (cut_name.length()>20) cut_name = cut_name.substr(0,20); // .at(0,20);

    // DRAW THE BOX
  drawsegment(minPmin, y_position , minMoyP , y_position);
  drawsegment(maxMoyP, y_position , maxPmax , y_position);
  drawbox(minMoyP,y_position-(box_width/2), (Pmoy-minMoyP), box_width);
  drawbox(Pmoy,y_position-(box_width/2),(maxMoyP-Pmoy), box_width);

    // DRAW THE BRACKET
  // the first one
  drawsegment(minPmin+0.005, y_position-(box_width/2) , 
              minPmin , y_position-(box_width/2));
  drawsegment(minPmin, y_position-(box_width/2) , 
              minPmin , y_position+(box_width/2));
  drawsegment(minPmin, y_position+(box_width/2) , 
              minPmin+0.005, y_position+(box_width/2));
  // the second one
  drawsegment(maxPmax-0.005, y_position-(box_width/2) , 
              maxPmax , y_position-(box_width/2));
  drawsegment(maxPmax, y_position-(box_width/2) , 
              maxPmax , y_position+(box_width/2));
  drawsegment(maxPmax, y_position+(box_width/2) , 
              maxPmax-0.005, y_position+(box_width/2));


  // GIVE DESCRIPTION
  VeryLongNatural buffer_length = 30;
  char buffer[buffer_length];
  drawlabel(1.05,y_position-(box_width/4),cut_name, 9.0);
  sprintf(buffer,": minPmin = %.3f   minPmoy = %.3f  Pmoy = %.3f", 
          minPmin, minMoyP, Pmoy);
  string system = string(buffer);
  drawlabel(1.14,y_position-(box_width/4),system, 9.0);
  sprintf(buffer,"  maxPmoy = %.3f maxPmax = %.3f     (%d)", 
          maxMoyP, maxPmax, NbrCase);
  system = string(buffer);
  drawlabel(1.14,y_position-(box_width/4)-0.025,system, 9.0);
  info_pos_y += line_space;
  system_char++;
}

#ifdef _USE_NAMESPACES
}
#endif // _USE_NAMESPACES

