<?php
/**
 * @version $Id$
 * @author Thomas Crespin <thomas.crespin@sesamath.net>
 * @copyright Thomas Crespin 2009-2022
 *
 * ****************************************************************************************************
 * SACoche <https://sacoche.sesamath.net> - Suivi d’Acquisitions de Compétences
 * © Thomas Crespin pour Sésamath <https://www.sesamath.net> - Tous droits réservés.
 * Logiciel placé sous la licence libre Affero GPL 3 <https://www.gnu.org/licenses/agpl-3.0.html>.
 * ****************************************************************************************************
 *
 * Ce fichier est une partie de SACoche.
 *
 * SACoche est un logiciel libre ; vous pouvez le redistribuer ou le modifier suivant les termes 
 * de la “GNU Affero General Public License” telle que publiée par la Free Software Foundation :
 * soit la version 3 de cette licence, soit (à votre gré) toute version ultérieure.
 *
 * SACoche est distribué dans l’espoir qu’il vous sera utile, mais SANS AUCUNE GARANTIE :
 * sans même la garantie implicite de COMMERCIALISABILITÉ ni d’ADÉQUATION À UN OBJECTIF PARTICULIER.
 * Consultez la Licence Publique Générale GNU Affero pour plus de détails.
 *
 * Vous devriez avoir reçu une copie de la Licence Publique Générale GNU Affero avec SACoche ;
 * si ce n’est pas le cas, consultez : <http://www.gnu.org/licenses/>.
 *
 */
 
// Extension de classe qui étend PDF

// Ces méthodes ne concernent que la mise en page d’un bilan d’items

class PDF_item_synthese extends PDF
{

  // initialiser()   --> c’est là que les calculs se font pour une sortie "matiere"
  // entete()        --> c’est là que les calculs se font pour une sortie "multimatiere"

  private function premiere_page()
  {
    $this->AddPage($this->orientation , $this->page_size);
    $this->page_numero_first = $this->page;
    $this->choisir_couleur_texte('gris_fonce');
    $this->SetFont(FONT_FAMILY , 'B' , 7);
    $this->Cell( $this->page_largeur_moins_marges , 4 /*ligne_hauteur*/ , To::pdf('Page 1/'.$this->page_nombre_alias) , 0 /*bordure*/ , 1 /*br*/ , $this->page_nombre_alignement , FALSE /*fond*/ );
    $this->choisir_couleur_texte('noir');
    $this->SetXY( $this->marge_gauche , $this->marge_haut );
  }

  private function rappel_eleve_page()
  {
    $this->AddPage($this->orientation , $this->page_size);
    $page_numero = $this->page - $this->page_numero_first + 1 ;
    $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police);
    $this->choisir_couleur_texte('gris_fonce');
    $this->Cell( $this->page_largeur_moins_marges , $this->lignes_hauteur , To::pdf($this->doc_titre.' - '.$this->eleve_nom_prenom.' - Page '.$page_numero.'/'.$this->page_nombre_alias) , 0 /*bordure*/ , 1 /*br*/ , $this->page_nombre_alignement , FALSE /*fond*/ );
    $this->choisir_couleur_texte('noir');
  }

  public function initialiser( $synthese_modele , $nb_lignes_total_synthese , $eleves_nb )
  {
    $this->synthese_modele = $synthese_modele;
    $this->SetMargins( $this->marge_gauche , $this->marge_haut , $this->marge_droite );
    $this->SetAutoPageBreak(FALSE);
    if($this->synthese_modele=='matiere')
    {
      // Dans ce cas on met plusieurs élèves par page : on calcule maintenant combien et la hauteur de ligne à prendre
      $hauteur_dispo_par_page     = $this->page_hauteur_moins_marges ;
      $lignes_nb_tous_eleves      = $eleves_nb * ( 1 + 1 + ($this->legende*1.5) ) + $nb_lignes_total_synthese ; // eleves * [ intitulé-structure + classe-élève-date + légende ] + toutes_synthèses
      $hauteur_ligne_moyenne      = 6;
      $lignes_nb_moyen_par_page   = $hauteur_dispo_par_page / $hauteur_ligne_moyenne ;
      $nb_page_moyen              = max( 1 , round( $lignes_nb_tous_eleves / $lignes_nb_moyen_par_page ) ); // max 1 pour éviter une division par zéro
      $eleves_nb_par_page         = ceil( $eleves_nb / $nb_page_moyen ) ;
      // $nb_page_calcule = ceil( $eleves_nb / $eleves_nb_par_page ) ; // devenu inutile
      $lignes_nb_moyen_eleve      = $lignes_nb_tous_eleves / $eleves_nb ;
      $lignes_nb_calcule_par_page = $eleves_nb_par_page * $lignes_nb_moyen_eleve ; // $lignes_nb/$nb_page_calcule ne va pas car un élève peut alors être considéré à cheval sur 2 pages
      $hauteur_ligne_calcule      = $hauteur_dispo_par_page / $lignes_nb_calcule_par_page ;
      $this->lignes_hauteur = Math::floorTo( $hauteur_ligne_calcule , 0.1 ) ; // valeur approchée au dixième près par défaut
      $this->lignes_hauteur = min ( $this->lignes_hauteur , 7.5 ) ;
      // On s’occupe aussi maintenant de la taille de la police
      $this->taille_police  = $this->lignes_hauteur * 1.6 ; // 5mm de hauteur par ligne donne une taille de 8
      $this->taille_police  = min ( $this->taille_police , 10 ) ;
      // Pour forcer à prendre une nouvelle page au 1er élève
      $this->SetXY( 0 , $this->page_hauteur );
    }
  }

  // Dernier paramètre uniquement pour un bulletin présenté comme tableau à double entrée (valeur initialement non transmise)
  public function entete( $tab_infos_entete , $eleve_nom_prenom , $eleve_INE , $eleve_nb_lignes , $tab_infos_croisement=NULL )
  {
    $this->eleve_nom_prenom = $eleve_nom_prenom;
    if($this->synthese_modele=='matiere')
    {
      // La hauteur de ligne a déjà été calculée ; mais il reste à déterminer si on saute une page ou non en fonction de la place restante (et sinon => interligne)
      $hauteur_dispo_restante = $this->page_hauteur - $this->GetY() - $this->marge_bas ;
      $lignes_nb = 1 + 1 + ($this->legende*1.5) + $eleve_nb_lignes ; // intitulé-structure + classe-élève-date + légende + synthèses
      if( $this->lignes_hauteur*$lignes_nb > $hauteur_dispo_restante )
      {
        $this->AddPage($this->orientation , $this->page_size);
      }
      else
      {
        // Interligne
        $this->SetXY( $this->marge_gauche , $this->GetY() + $this->lignes_hauteur*1.5 );
      }
    }
    else // multimatiere | matieres
    {
      // On prend une nouvelle page PDF
      $this->premiere_page();
      if($this->officiel)
      {
        // Ecrire l’en-tête (qui ne dépend pas de la taille de la police calculée ensuite) et récupérer la place requise par cet en-tête.
        extract($tab_infos_entete); // $tab_etabl_coords , $tab_etabl_logo , $etabl_coords_bloc_hauteur , $tab_bloc_titres , $tab_adresse , $tag_date_heure_initiales , $eleve_genre , $date_naissance
        $this->doc_titre = $tab_bloc_titres[0].' - '.$tab_bloc_titres[1];
        // Bloc adresse en positionnement contraint
        if( (is_array($tab_adresse)) && ($this->SESSION['OFFICIEL']['INFOS_RESPONSABLES']=='oui_force') )
        {
          list( $bloc_droite_hauteur , $bloc_gauche_largeur_restante ) = $this->officiel_bloc_adresse_position_contrainte_et_pliures($tab_adresse);
          $this->SetXY( $this->marge_gauche , $this->marge_haut );
        }
        // Bloc établissement
        $bloc_etabl_largeur = (isset($bloc_gauche_largeur_restante)) ? $bloc_gauche_largeur_restante : $this->page_largeur_moins_marges / 2 ;
        $bloc_etabl_hauteur = $this->officiel_bloc_etablissement( $tab_etabl_coords , $tab_etabl_logo , $bloc_etabl_largeur );
        // Bloc titres
        if( (is_array($tab_adresse)) && ($this->SESSION['OFFICIEL']['INFOS_RESPONSABLES']=='oui_force') )
        {
          // En dessous du bloc établissement
          $bloc_titre_largeur = $bloc_etabl_largeur ;
          $this->SetXY( $this->marge_gauche , $this->GetY() + 2 );
          $bloc_titre_hauteur = $this->officiel_bloc_titres( $tab_bloc_titres , $bloc_titre_largeur );
          $bloc_gauche_hauteur = $bloc_etabl_hauteur + 2 + $bloc_titre_hauteur + 2 ;
        }
        else
        {
          // En haut à droite, modulo la place pour le texte indiquant le nombre de pages
          $bloc_titre_largeur = $this->page_largeur_moins_marges / 2;
          $this->SetXY( $this->page_largeur-$this->marge_droite-$bloc_titre_largeur , $this->marge_haut+4 );
          $bloc_titre_hauteur = $this->officiel_bloc_titres( $tab_bloc_titres , $bloc_titre_largeur) + 6;
          $bloc_gauche_hauteur = $bloc_etabl_hauteur ;
          $bloc_droite_hauteur = $bloc_titre_hauteur ; // temporaire, au cas où il n’y aurait pas d’adresse à ajouter
        }
        // Date de naissance + Tag date heure initiales (sous le bloc titres dans toutes les situations)
        $this->officiel_ligne_tag( $eleve_genre , $date_naissance , $eleve_INE , $tag_date_heure_initiales , $bloc_titre_largeur );
        // Bloc adresse en positionnement libre
        if( (is_array($tab_adresse)) && ($this->SESSION['OFFICIEL']['INFOS_RESPONSABLES']=='oui_libre') )
        {
          $bloc_adresse_largeur = $bloc_titre_largeur - 10; // Pour avoir un petit décalage par rapport au bloc titre
          $this->SetXY( $this->page_largeur-$this->marge_droite-$bloc_adresse_largeur , $this->marge_haut+$bloc_titre_hauteur+4 );
          $bloc_adresse_hauteur = $this->officiel_bloc_adresse_position_libre($tab_adresse,$bloc_adresse_largeur);
          $bloc_droite_hauteur = $bloc_titre_hauteur + $bloc_adresse_hauteur ;
        }
        $hauteur_entete = max($bloc_gauche_hauteur,$bloc_droite_hauteur);
      }
      else
      {
        $hauteur_entete = 2*4 ; // HG L1 intitulé L2 période ; HD L1 structure L2 élève classe
      }
      // On calcule la hauteur de la ligne et la taille de la police pour tout faire rentrer sur une page si possible (personnalisée par élève), un minimum de pages sinon
      $hauteur_dispo_par_page = $this->page_hauteur_moins_marges ;
      $lignes_nb = ( $hauteur_entete / 4 ) + $eleve_nb_lignes + ($this->legende*1.5) ; // en-tête + synthèses + légendes
      $hauteur_ligne_minimale = ($this->officiel) ? 4 : 3.5 ;
      $hauteur_ligne_maximale = $hauteur_ligne_minimale + 2;
      $nb_pages = 0;
      do
      {
        $nb_pages++;
        $lignes_rabe = ($nb_pages-1)*10; // Prendre un peu de marge pour tenir compte des sauts de page laissant du blanc en bas de page si une rubrique ne rentre pas.
        $hauteur_ligne_calcule = $nb_pages*$hauteur_dispo_par_page / ($lignes_nb+$lignes_rabe) ;
      }
      while($hauteur_ligne_calcule < $hauteur_ligne_minimale);
      // En cas de bilan officiel présenté comme un tableau à double entrée, on s'arrange pour que le tableau soit complet sur la 1ère page.
      if(!is_null($tab_infos_croisement))
      {
        extract($tab_infos_croisement);  // $eleve_nb_blocs $eleve_nb_lignes_hors_synthese
        if($nb_pages>1)
        {
          $hauteur_tableau       = $hauteur_dispo_par_page - $hauteur_entete;
          $this->cases_hauteur   = $hauteur_tableau / $eleve_nb_blocs;
          $hauteur_ligne_calcule = $hauteur_ligne_minimale;
        }
        else
        {
          $this->cases_hauteur   = ( $hauteur_ligne_calcule * ( $eleve_nb_lignes - $eleve_nb_lignes_hors_synthese ) ) / $eleve_nb_blocs;
        }
        // Pour ne pas avoir les scores dans les cases
        $this->afficher_score = FALSE;
      }
      $this->lignes_hauteur = Math::floorTo( $hauteur_ligne_calcule , 0.1 ) ; // valeur approchée au dixième près par défaut
      $this->lignes_hauteur = min ( $this->lignes_hauteur , $hauteur_ligne_maximale ) ;
      $this->taille_police  = $this->lignes_hauteur * 1.6 ; // 5mm de hauteur par ligne donne une taille de 8
      $this->taille_police  = min ( $this->taille_police , 10 ) ;
    }
    if(!$this->officiel)
    {
      extract($tab_infos_entete); // $bilan_titre , $texte_periode , $texte_precision , $groupe_nom
      $this->doc_titre = 'Synthèse '.$bilan_titre.' - '.$texte_periode;
      // Intitulé (dont éventuellement matière) / structure
      $largeur_demi_page = ( $this->page_largeur_moins_marges ) / 2;
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.5);
      $this->Cell( $largeur_demi_page , $this->lignes_hauteur , To::pdf('Synthèse '.$bilan_titre)                     , 0 /*bordure*/ , 0 /*br*/ , 'L' /*alignement*/ , FALSE /*fond*/ );
      $this->Cell( $largeur_demi_page , $this->lignes_hauteur , To::pdf($this->SESSION['ETABLISSEMENT_DENOMINATION']) , 0 /*bordure*/ , 1 /*br*/ , 'R' /*alignement*/ , FALSE /*fond*/ );
      // Période / Classe - élève
      $memo_y = $this->GetY();
      $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
      $this->SetXY( $this->GetX() , $this->GetY() - $this->lignes_hauteur*0.2 );
      $this->Cell( $largeur_demi_page , $this->taille_police*0.8 , To::pdf($texte_periode)   , 0 /*bordure*/ , 1 /*br*/ , 'L' /*alignement*/ , FALSE /*fond*/ );
      $this->SetXY( $this->GetX() , $this->GetY() - $this->lignes_hauteur*0.6 );
      $this->Cell( $largeur_demi_page , $this->taille_police*0.8 , To::pdf($texte_precision) , 0 /*bordure*/ , 1 /*br*/ , 'L' /*alignement*/ , FALSE /*fond*/ );
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.5);
      $this->SetXY( $this->marge_gauche + $largeur_demi_page , $memo_y - $this->lignes_hauteur*0.1 );
      $this->Cell( $largeur_demi_page , $this->lignes_hauteur , To::pdf($this->eleve_nom_prenom.' ('.$groupe_nom.')') , 0 /*bordure*/ , 1 /*br*/ , 'R' /*alignement*/ , FALSE /*fond*/ );
      if($this->synthese_modele=='matiere')
      {
        $this->SetXY( $this->marge_gauche , $this->GetY() + $this->lignes_hauteur*0.5 );
      }
    }
    else // multimatiere | matieres
    {
      $this->SetXY( $this->marge_gauche , $this->marge_haut + $hauteur_entete );
    }
  }

  public function ligne_matiere( $matiere_nom , $lignes_nb , $tab_infos_matiere , $total , $moyenne_eleve , $moyenne_classe , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation=FALSE )
  {
    if($this->synthese_modele!='matiere') // multimatiere | matieres
    {
      // La hauteur de ligne a déjà été calculée ; mais il reste à déterminer si on saute une page ou non en fonction de la place restante (et sinon => interligne)
      $hauteur_dispo_restante = $this->page_hauteur - $this->GetY() - $this->marge_bas ;
      $test_nouvelle_page = ($this->lignes_hauteur*$lignes_nb > $hauteur_dispo_restante) && ($this->GetY() > $this->lignes_hauteur*5) ; // 2e condition pour éviter un saut de page si déjà en haut (à cause d’une liste à rallonge dans une matière)
      if( $test_nouvelle_page )
      {
        $this->rappel_eleve_page();
      }
      else
      {
        // Interligne
        $nb_lignes_vides = ($this->officiel) ? 1 : 1.5 ;
        $this->SetXY($this->marge_gauche , $this->GetY() + $this->lignes_hauteur*$nb_lignes_vides);
      }
    }
    if(!$this->officiel)
    {
      // Intitulé matière
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.25);
      $couleur_fond = ($this->couleur=='oui') ? 'gris_moyen' : 'blanc' ; // Forcer un fond blanc en cas d’impression en niveau de gris sinon c’est très confus
      $this->choisir_couleur_fond($couleur_fond);
      $this->CellFit( $this->page_largeur_moins_marges - 80 , $this->lignes_hauteur*1.5 , To::pdf($matiere_nom) , 1 /*bordure*/ , 0 /*br*/ , 'L' /*alignement*/ , $this->fond );
      // Proportions acquis matière
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police);
      $this->afficher_proportion_acquis( 80 , $this->lignes_hauteur*1.5 , $tab_infos_matiere , $total , $avec_texte_nombre , $avec_texte_code );
      // Interligne
      $this->SetXY($this->marge_gauche , $this->GetY() + $this->lignes_hauteur*1.5);
    }
    else
    {
      $memo_y = $this->GetY();
      $demi_largeur = ( ($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) || ($this->SESSION['OFFICIEL']['BULLETIN_BARRE_ACQUISITIONS']) || !$sans_cadre_appreciation ) ? ( $this->page_largeur_moins_marges ) / 2  : $this->page_largeur_moins_marges ;
      // Intitulé matière
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.25);
      $couleur_fond = ($this->couleur=='oui') ? 'gris_moyen' : 'blanc' ; // Forcer un fond blanc en cas d’impression en niveau de gris sinon c’est très confus
      $this->choisir_couleur_fond($couleur_fond);
      $this->CellFit( $demi_largeur , $this->lignes_hauteur*2 , To::pdf($matiere_nom) , 1 /*bordure*/ , 0 /*br*/ , 'L' /*alignement*/ , $this->fond );
      // Moyenne élève (éventuelle) et moyenne classe (éventuelle)
      if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
      {
        $objet = ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? 'Moyenne' : 'Pourcentage' ;
        $nb_lignes_hauteur = 2 - $this->SESSION['OFFICIEL']['BULLETIN_BARRE_ACQUISITIONS'] ;
        $largeur_note = 10;
        $this->Rect( $this->GetX() , $this->GetY() , $demi_largeur , $this->lignes_hauteur*$nb_lignes_hauteur , 'D' /* DrawFill */ );
        $texte = ($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) ? $objet.' élève (classe) :' : $objet.' élève :' ;
        $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
        $largueur_texte = ($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) ? $demi_largeur-2*$largeur_note : $demi_largeur-$largeur_note ;
        $this->Cell( $largueur_texte , $this->lignes_hauteur*$nb_lignes_hauteur , To::pdf($texte) , 0 /*bordure*/ , 0 /*br*/ , 'R' /*alignement*/ , FALSE /*fond*/ );
        $moyenne_eleve = ($moyenne_eleve!==NULL) ? ( ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? number_format($moyenne_eleve,1,',','') : ($moyenne_eleve*5).'%' ) : '-' ;
        $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.25);
        $this->Cell( $largeur_note , $this->lignes_hauteur*$nb_lignes_hauteur , To::pdf($moyenne_eleve) , 0 /*bordure*/ , 0 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
        if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
        {
          $moyenne_classe = ($moyenne_classe!==NULL) ? ( ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? number_format($moyenne_classe,1,',','') : round($moyenne_classe*5).'%' ) : '-' ;
          $this->SetFont(FONT_FAMILY , '' , $this->taille_police*0.8);
          $this->Cell( $largeur_note , $this->lignes_hauteur*$nb_lignes_hauteur , To::pdf('('.$moyenne_classe.')') , 0 /*bordure*/ , 0 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
        }
        $this->SetXY($this->marge_gauche + $demi_largeur , $this->GetY() + $this->lignes_hauteur*$nb_lignes_hauteur );
      }
      // Proportions acquis matière
      if($this->SESSION['OFFICIEL']['BULLETIN_BARRE_ACQUISITIONS'])
      {
        $nb_lignes_hauteur = 2 - $this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'] ;
        $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
        $this->afficher_proportion_acquis( $demi_largeur , $this->lignes_hauteur*$nb_lignes_hauteur , $tab_infos_matiere , $total , $avec_texte_nombre , $avec_texte_code );
      }
      // Positionnement
      $this->SetXY( $this->marge_gauche , $memo_y + $this->lignes_hauteur*2 );
    }
  }

  public function ligne_synthese( $synthese_nom , $tab_infos_synthese , $total , $hauteur_ligne_synthese , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation=FALSE )
  {
    $hauteur_ligne = $this->lignes_hauteur * $hauteur_ligne_synthese ;
    $largeur_diagramme = ($this->officiel) ? 20 : 40 ;
    $this->SetFont(FONT_FAMILY , '' , $this->taille_police*0.8);
    $this->afficher_proportion_acquis( $largeur_diagramme , $hauteur_ligne , $tab_infos_synthese , $total,$avec_texte_nombre , $avec_texte_code );
    $intitule_synthese_largeur = ( ($this->officiel) && ($this->SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR']) && !$sans_cadre_appreciation ) ? ( $this->page_largeur_moins_marges ) / 2 - $largeur_diagramme : $this->page_largeur_moins_marges - $largeur_diagramme ;
    // Intitulé synthèse
    $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
    $couleur_fond = ($this->couleur=='oui') ? 'gris_clair' : 'blanc' ; // Forcer un fond blanc en cas d’impression en niveau de gris sinon c’est très confus
    $this->choisir_couleur_fond($couleur_fond);
    $this->CellFit( $intitule_synthese_largeur , $hauteur_ligne , To::pdf($synthese_nom) , 1 /*bordure*/ , 1 /*br*/ , 'L' /*alignement*/ , $this->fond );
  }

  public function appreciation_rubrique( $tab_saisie , $nb_lignes_hauteur , $sans_cadre_appreciation=FALSE )
  {
    $cadre_hauteur = $nb_lignes_hauteur * $this->lignes_hauteur ;
    $demi_largeur = ( $this->page_largeur_moins_marges ) / 2 ;
    if(!$sans_cadre_appreciation)
    {
      $this->SetXY( $this->marge_gauche + $demi_largeur , $this->GetY() - $cadre_hauteur );
      $this->Rect( $this->GetX() , $this->GetY() , $demi_largeur , $cadre_hauteur , 'D' /* DrawFill */ );
    }
    if($tab_saisie!==NULL)
    {
      unset($tab_saisie[0]); // la note
      $memo_y = $this->GetY();
      $this->officiel_bloc_appreciation_intermediaire( $tab_saisie , $demi_largeur , $this->lignes_hauteur , 'bulletin' , $cadre_hauteur );
      $this->SetXY( $this->marge_gauche , $memo_y + $cadre_hauteur );
    }
    else
    {
      $this->SetXY( $this->marge_gauche , $this->GetY() + $cadre_hauteur );
    }
  }

  public function ligne_tableau_entete( $tab_croisement_synthese , $nb_format_synthese_differents , $synthese_ref_height )
  {
    $coef_largeur_colonne_matiere        = 3.5;
    $coef_largeur_colonne_appreciation   = 10;
    $coef_largeur_colonne_positionnement = 1.5;
    $this->cases_largeur = $this->page_largeur_moins_marges / ( $coef_largeur_colonne_matiere + $nb_format_synthese_differents + $coef_largeur_colonne_appreciation + $coef_largeur_colonne_positionnement*$this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']); // matière/prof + cases synthèses + appréciation + note éventuelle
    $hauteur_ligne_entete = $this->cases_hauteur*$synthese_ref_height;
    // Interligne & décalage colonne matière
    $this->SetXY($this->marge_gauche + $coef_largeur_colonne_matiere*$this->cases_largeur , $this->GetY() + $this->lignes_hauteur);
    $memo_x = $this->GetX();
    $memo_y = $this->GetY();
    // Cases synthèses
    $couleur_fond = ($this->couleur=='oui') ? 'gris_clair' : 'blanc' ; // Forcer un fond blanc en cas d’impression en niveau de gris sinon c’est très confus
    $this->choisir_couleur_fond($couleur_fond);
    $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
    foreach($tab_croisement_synthese as $synthese_nom)
    {
      $synthese_longueur = mb_strlen($synthese_nom);
      $test_longueur = sqrt($synthese_longueur/10);
      $test_nb_mots = str_word_count($synthese_nom);
      if( ($test_nb_mots==1) || ($test_longueur<=$synthese_ref_height ) )
      {
        $this->VertCellFit( $this->cases_largeur, $hauteur_ligne_entete, To::pdf($synthese_nom), 1 /*border*/ , 0 /*ln*/ , TRUE /*fill*/ );
      }
      else
      {
        // on écrit l’intitulé à la verticale avec un retour à la ligne
        $tab_mots = str_word_count($synthese_nom,2);
        $position_moitie = $synthese_longueur / 2 ;
        foreach( $tab_mots as $mot_position => $mot_texte)
        {
          if($mot_position >= $position_moitie)
          {
            break;
          }
        }
        $synthese_nom_partie_1 = mb_substr( $synthese_nom , 0 , $mot_position-1);
        $synthese_nom_partie_2 = mb_substr( $synthese_nom , $mot_position-1);
        $this->Rect( $this->GetX() , $this->GetY() , $this->cases_largeur , $hauteur_ligne_entete , 'DF' /* DrawFill */ );
        $this->VertCellFit( $this->cases_largeur/2, $hauteur_ligne_entete, To::pdf($synthese_nom_partie_1), 0 /*border*/ , 0 /*ln*/ , FALSE /*fill*/ );
        $this->VertCellFit( $this->cases_largeur/2, $hauteur_ligne_entete, To::pdf($synthese_nom_partie_2), 0 /*border*/ , 0 /*ln*/ , FALSE /*fill*/ );
      }
    }
    // Appréciation
    $coef_interligne = 0.7;
    $marge_gauche = $this->cases_largeur ;
    $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.2);
    $this->SetXY( $this->GetX() + $marge_gauche , $this->GetY() + $hauteur_ligne_entete - 2*$coef_interligne*$this->lignes_hauteur );
    $this->CellFit( $coef_largeur_colonne_appreciation*$this->cases_largeur - $marge_gauche , $this->lignes_hauteur , To::pdf('Appréciations / Conseils') , 0 /*bordure*/ , 0 /*br*/ , 'L' /*alignement*/ , FALSE /*fond*/ );
    // Moyenne élève (éventuelle) et moyenne classe (éventuelle)
    if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
    {
      $largueur_moyenne = $coef_largeur_colonne_positionnement*$this->cases_largeur;
      $decalage_y = ($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) ? $coef_interligne*$this->lignes_hauteur : 0 ;
      $this->SetXY( $this->GetX() , $this->GetY() - $decalage_y );
      $objet = ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? 'Moyenne' : 'Pourcentage' ;
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police);
      $this->CellFit( $largueur_moyenne , $coef_interligne*$this->lignes_hauteur , To::pdf($objet ) , 0 /*bordure*/ , 2 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
      $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
      $this->CellFit( $largueur_moyenne , $coef_interligne*$this->lignes_hauteur , To::pdf('élève') , 0 /*bordure*/ , 2 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
      if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
      {
        $this->SetFont(FONT_FAMILY , '' , $this->taille_police*0.8);
        $this->CellFit( $largueur_moyenne , $coef_interligne*$this->lignes_hauteur , To::pdf('(classe)') , 0 /*bordure*/ , 1 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
      }
    }
    $this->SetXY( $this->marge_gauche , $memo_y + $hauteur_ligne_entete );
  }

  public function ligne_tableau_matiere( $tab_croisement_synthese , $matiere_id , $matiere_nom , $tab_score , $tab_saisie , $moyenne_eleve , $moyenne_classe )
  {
    $coef_largeur_colonne_matiere        = 3.5;
    $coef_largeur_colonne_appreciation   = 10;
    $coef_largeur_colonne_positionnement = 1.5;
    // On extrait et on assemble si besoin les appréciations
    $tab_prof = array();
    $texte_appreciation = '';
    if($tab_saisie!==NULL)
    {
      unset($tab_saisie[0]); // la note
      $nb_caracteres_maxi = $this->SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR'];
      $nb_lignes_appreciation_potentielle_par_prof_hors_intitule = $nb_caracteres_maxi / 100 / 2 ;
      $nb_lignes_prevues = 0;
      $nb_saisies = count($tab_saisie);
      $tab_crlf = Clean::tab_crlf();
      foreach($tab_saisie as $prof_id => $tab)
      {
        extract($tab);  // $prof_info $appreciation $note
        $tab_prof[] = $prof_info;
        if($nb_saisies==1)
        {
          $texte_appreciation .= $appreciation;
        }
        else
        {
          $nom_auteur = '[ '.$prof_info.' ] '; // associer le nom de l’auteur avec l’appréciation si plusieurs appréciations pour une même rubrique
          $appreciation_sans_br = str_replace( $tab_crlf , ' ' , $appreciation , $nombre_br );
          $texte_appreciation .= ($nombre_br<4-$nb_saisies) ? $nom_auteur.$appreciation."\n" : $nom_auteur.$appreciation_sans_br."\n" ;
        }
        $nb_lignes_prevues += $nb_lignes_appreciation_potentielle_par_prof_hors_intitule;
      }
    }
    // On commence par une case avec le nom de la matière et les noms des profs
    $matiere_largeur = $coef_largeur_colonne_matiere*$this->cases_largeur;
    $memo_x = $this->GetX();
    $memo_y = $this->GetY();
    $couleur_fond = ($this->couleur=='oui') ? 'gris_moyen' : 'blanc' ; // Forcer un fond blanc en cas d’impression en niveau de gris sinon c’est très confus
    $this->choisir_couleur_fond($couleur_fond);
    $this->Rect( $memo_x , $memo_y , $matiere_largeur , $this->cases_hauteur , 'DF' /* DrawFill */ );
    $nb_lignes_matiere = ( strlen($matiere_nom) > 25 ) ? 2.5 : 1.5 ;
    $nb_lignes_profs = count($tab_prof);
    $nb_lignes_total = $nb_lignes_matiere + $nb_lignes_profs;
    $lignes_hauteur = min( $this->lignes_hauteur , $this->cases_hauteur / $nb_lignes_total ) ;
    $this->SetXY( $memo_x , $memo_y + ($this->cases_hauteur/2) - ($lignes_hauteur*$nb_lignes_total)/2 );
    $taille_interligne = $lignes_hauteur*0.8;
    $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police);
    $this->afficher_appreciation( $matiere_largeur , $lignes_hauteur*$nb_lignes_matiere , $this->taille_police , $taille_interligne , $matiere_nom , 'B' /*bold*/ );
    $this->SetFont(FONT_FAMILY , '' , $this->taille_police);
    foreach($tab_prof as $prof_info)
    {
      $this->CellFit( $matiere_largeur , $lignes_hauteur , To::pdf($prof_info) , 0 /*bordure*/ , 2 /*br*/ , 'L' /*alignement*/ , FALSE /*fond*/ );
    }
    $this->SetXY( $memo_x + $matiere_largeur , $memo_y );
    // Ensuite on passe aux cases pour les états par format de synthèse
    foreach($tab_croisement_synthese as $synthese_ref_fin => $synthese_nom)
    {
      $synthese_ref = $matiere_id.'_'.$synthese_ref_fin;
      $score = isset($tab_score[$synthese_ref]) ? $tab_score[$synthese_ref] : FALSE ;
      $this->afficher_score_bilan( $score , 0 /*br*/, FALSE /*bold*/ );
    }
    // Case avec la ou les appréciation(s)
    $memo_x = $this->GetX();
    $bloc_largeur = $coef_largeur_colonne_appreciation*$this->cases_largeur;
    $taille_police = $this->taille_police*1.2;
    $taille_interligne = $this->lignes_hauteur*0.8;
    $this->afficher_appreciation( $bloc_largeur , $this->cases_hauteur , $taille_police , $taille_interligne , $texte_appreciation );
    $this->Rect( $memo_x , $memo_y , $bloc_largeur , $this->cases_hauteur , 'D' /* DrawFill */ );
    $this->SetXY( $memo_x + $bloc_largeur , $memo_y );
    // On termine avec la case pour la moyenne élève (éventuelle) et la moyenne classe (éventuelle)
    $note_largeur = $coef_largeur_colonne_positionnement*$this->cases_largeur;
    if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
    {
      $memo_x = $this->GetX();
      $this->Rect( $this->GetX() , $this->GetY() , $note_largeur , $this->cases_hauteur , 'D' /* DrawFill */ );
      $decalage_y = ($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) ? ($this->cases_hauteur/2)-$this->lignes_hauteur : ($this->cases_hauteur/2)-($this->lignes_hauteur/2) ;
      $this->SetXY( $memo_x , $memo_y + $decalage_y );
      $moyenne_eleve = ($moyenne_eleve!==NULL) ? ( ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? number_format($moyenne_eleve,1,',','') : ($moyenne_eleve*5).'%' ) : '-' ;
      $this->SetFont(FONT_FAMILY , 'B' , $this->taille_police*1.25);
      $this->Cell( $note_largeur , $this->lignes_hauteur , To::pdf($moyenne_eleve) , 0 /*bordure*/ , 2 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
      if($this->SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
      {
        $moyenne_classe = ($moyenne_classe!==NULL) ? ( ($this->SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? number_format($moyenne_classe,1,',','') : round($moyenne_classe*5).'%' ) : '-' ;
        $this->SetFont(FONT_FAMILY , '' , $this->taille_police*0.8);
        $this->Cell( $note_largeur , $this->lignes_hauteur , To::pdf('('.$moyenne_classe.')') , 0 /*bordure*/ , 1 /*br*/ , 'C' /*alignement*/ , FALSE /*fond*/ );
      }
    }
    $this->SetXY($this->marge_gauche , $memo_y + $this->cases_hauteur );
  }

  public function appreciation_generale( $prof_id , $tab_infos , $tab_image_tampon_signature , $nb_lignes_appreciation_generale_avec_intitule , $nb_lignes_assiduite_et_pp_et_message_et_legende , $moyenne_generale_eleve , $moyenne_generale_classe )
  {
    $hauteur_restante = $this->page_hauteur - $this->GetY() - $this->marge_bas;
    $hauteur_requise = $this->lignes_hauteur * ( $nb_lignes_appreciation_generale_avec_intitule + $nb_lignes_assiduite_et_pp_et_message_et_legende ) ;
    if($hauteur_requise > $hauteur_restante)
    {
      // Prendre une nouvelle page si ça ne rentre pas, avec recopie de l’identité de l’élève
      $this->rappel_eleve_page();
      $this->SetXY( $this->marge_gauche , $this->GetY() + 2 );
    }
    else
    {
      // Interligne
      $this->SetXY($this->marge_gauche , $this->GetY() + $this->lignes_hauteur*0.5);
    }
    $this->officiel_bloc_appreciation_generale( $prof_id , $tab_infos , $tab_image_tampon_signature , $nb_lignes_appreciation_generale_avec_intitule , $this->page_largeur_moins_marges , $this->lignes_hauteur , $moyenne_generale_eleve , $moyenne_generale_classe );
  }

  public function legende($aff_prop_sans_score = FALSE)
  {
    // Légende : en bas de page si 'multimatiere' ou 'matieres', à la suite si 'matiere'
    $ordonnee = ($this->synthese_modele!='matiere') ?  $this->page_hauteur - $this->marge_bas - $this->lignes_hauteur*0.5 : $this->GetY() + $this->lignes_hauteur*0.5 ;
    $this->afficher_legende( 'etat_acquisition' /*type_legende*/ , $ordonnee , $aff_prop_sans_score );
  }

}
?>