<?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/>.
 * 
 */

if(!defined('SACoche')) {exit('Ce fichier ne peut être appelé directement !');}

/**
 * Code inclus commun aux pages
 * [./pages/releve_synthese.ajax.php]
 * [./_inc/code_officiel_***.php]
 */

Erreur500::prevention_et_gestion_erreurs_fatales( TRUE /*memory*/ , FALSE /*time*/ );

/*
$type_individuel | $type_synthese
*/

// Chemins d’enregistrement

$fichier_nom = ($make_action!='imprimer') ? 'releve_synthese_'.$synthese_modele.'_'.Clean::fichier($groupe_nom).'_<REPLACE>_'.FileSystem::generer_fin_nom_fichier__date_et_alea() : 'officiel_'.$BILAN_TYPE.'_'.Clean::fichier($groupe_nom).'_'.FileSystem::generer_fin_nom_fichier__date_et_alea() ;

// Initialisation de tableaux

$tab_item_infos    = array();  // [item_id] => array(item_ref,item_nom,item_coef,item_cart,item_s2016,item_lien,matiere_id,calcul_methode,calcul_limite,calcul_retroactif,synthese_ref);
$tab_liste_item    = array();  // [i] => item_id
$tab_eleve_infos   = array();  // [eleve_id] => array(eleve_INE,eleve_nom,eleve_prenom,date_naissance)
$tab_matiere       = array();  // [matiere_id] => array(matiere_nom,matiere_nb_demandes)
$tab_synthese      = array();  // [synthese_ref] => synthese_nom
$tab_eval          = array();  // [eleve_id][item_id][devoir] => array(note,date,info) On utilise un tableau multidimensionnel vu qu’on ne sait pas à l’avance combien il y a d’évaluations pour un élève et un item donnés.
$tab_remove_strong = array('<strong>','</strong>');

$tab_precision_retroactif = array
(
  'auto'   => 'notes antérieures selon référentiels',
  'oui'    => $tab_remove_strong[0].'avec notes antérieures'.$tab_remove_strong[1],
  'non'    => $tab_remove_strong[0].'sans notes antérieures'.$tab_remove_strong[1],
  'annuel' => $tab_remove_strong[0].'notes antérieures de l’année scolaire'.$tab_remove_strong[1],
);

$info_ponderation = ($with_coef) ? '(pondérée)' : '(non pondérée)' ;

$tab_precision_synthese_indicateur = array
(
  'moyenne_pourcentages' => 'Moyenne '.$info_ponderation.' des pourcentages d’acquisition',
  'pourcentage_acquis'   => 'Pourcentage d’items acquis',
);

// Initialisation de variables

if( ($make_html) || ($make_pdf) || ($make_graph) )
{
  $tab_titre = array(
    'matiere'      => 'd’une matière - '.$matiere_nom ,
    'matieres'     => 'de matières sélectionnées' ,
    'multimatiere' => 'pluridisciplinaire' ,
  );
  if(!$aff_coef)  { $texte_coef       = ''; }
  if(!$aff_socle) { $texte_s2016      = ''; }
  if(!$aff_lien)  { $texte_lien_avant = ''; }
  if(!$aff_lien)  { $texte_lien_apres = ''; }
  $toggle_class = ($aff_start) ? 'toggle_moins' : 'toggle_plus' ;
  $toggle_etat  = ($aff_start) ? '' : ' class="hide"' ;
  $avec_texte_nombre = ( !$make_officiel || $_SESSION['OFFICIEL']['BULLETIN_ACQUIS_TEXTE_NOMBRE'] ) ? TRUE : FALSE ;
  $avec_texte_code   = ( !$make_officiel || $_SESSION['OFFICIEL']['BULLETIN_ACQUIS_TEXTE_CODE']   ) ? TRUE : FALSE ;
}

$precision_socle      = $only_socle ? ', '.$tab_remove_strong[0].'restreint au socle'.$tab_remove_strong[1] : '' ;
$precision_diagnostic = ($only_diagnostic=='oui') ? ', '.$tab_remove_strong[0].'restreint aux évaluations diagnostiques'.$tab_remove_strong[1] : '' ;
$precision_prof       = $only_prof ? ', '.$tab_remove_strong[0].'restreint à '.$prof_texte.$tab_remove_strong[1] : '' ;
$precision_niveau     = $only_niveau ? ', '.$tab_remove_strong[0].'restreint au niveau de l’élève'.$tab_remove_strong[1] : '' ;

$texte_precision_html    = $tab_precision_retroactif[$retroactif].$precision_socle.$precision_diagnostic.$precision_prof.$precision_niveau;
$texte_precision_pdf_csv = str_replace($tab_remove_strong,'',$texte_precision_html);

$texte_synthese_indicateur_html    = $tab_remove_strong[0].$tab_precision_synthese_indicateur[$synthese_indicateur].$tab_remove_strong[1];
$texte_synthese_indicateur_pdf_csv = str_replace($tab_remove_strong,'',$texte_synthese_indicateur_html);

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Période concernée
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if(!$periode_id)
{
  $date_sql_debut = To::date_french_to_sql($date_debut);
  $date_sql_fin   = To::date_french_to_sql($date_fin);
}
else
{
  $DB_ROW = DB_STRUCTURE_COMMUN::DB_recuperer_dates_periode($groupe_id,$periode_id);
  if(empty($DB_ROW))
  {
    Json::end( FALSE , 'Le regroupement et la période ne sont pas reliés !' );
  }
  $date_sql_debut = $DB_ROW['jointure_date_debut'];
  $date_sql_fin   = $DB_ROW['jointure_date_fin'];
  $date_debut = To::date_sql_to_french($date_sql_debut);
  $date_fin   = To::date_sql_to_french($date_sql_fin);
}
if($date_sql_debut>$date_sql_fin)
{
  Json::end( FALSE , 'La date de début est postérieure à la date de fin !' );
}

$texte_periode = 'Du '.$date_debut.' au '.$date_fin.'.';

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Récupération de la liste des items travaillés durant la période choisie, pour les élèves selectionnés, toutes matières confondues
// Récupération de la liste des synthèses concernées (nom de thèmes ou de domaines suivant les référentiels)
// Récupération de la liste des matières concernées
// ////////////////////////////////////////////////////////////////////////////////////////////////////

$only_prof_id = ($only_prof) ? $prof_id : FALSE ;
$without_matiere_experimentale = ( $make_officiel || in_array($_SESSION['USER_PROFIL_TYPE'],array('eleve','parent')) ) ? TRUE : FALSE ;

if(empty($is_appreciation_groupe))
{
  if($synthese_modele=='matiere')
  {
    list($tab_item_infos,$tab_synthese) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_synthese( $liste_eleve , $matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $only_niveau , $without_matiere_experimentale , $mode_synthese , $fusion_niveaux , $date_sql_debut , $date_sql_fin , $aff_socle , FALSE /*$order_synthese*/ );
    $tab_matiere[$matiere_id] = array(
      'matiere_nom'         => $matiere_nom,
      'matiere_nb_demandes' => DB_STRUCTURE_DEMANDE::DB_recuperer_demandes_autorisees_matiere($matiere_id),
    );
  }
  elseif($synthese_modele=='multimatiere')
  {
    $matiere_id = 0;
    $order_synthese = ( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') ) ? TRUE : FALSE ;
    list($tab_item_infos,$tab_synthese,$tab_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_synthese( $liste_eleve , $matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $only_niveau , $without_matiere_experimentale , 'predefini' /*mode_synthese*/ , $fusion_niveaux , $date_sql_debut , $date_sql_fin , $aff_socle , $order_synthese );
  }
  elseif($synthese_modele=='matieres')
  {
    $matiere_id = 0;
    list($tab_item_infos,$tab_synthese,$tab_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_synthese( $liste_eleve , $liste_matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $only_niveau , $without_matiere_experimentale , 'predefini' /*mode_synthese*/ , $fusion_niveaux , $date_sql_debut , $date_sql_fin , $aff_socle , FALSE /*$order_synthese*/ );
  }
}
else
{
  // Dans le cas d’une saisie globale sur le groupe, il faut "juste" récupérer les matières concernées.
  $liste_matiere_id = isset($liste_matiere_id) ? $liste_matiere_id : '' ;
  $DB_TAB = DB_STRUCTURE_BILAN::DB_recuperer_matieres_travaillees( $classe_id , $liste_matiere_id , $date_sql_debut , $date_sql_fin , TRUE /*only_if_synthese*/ );
  foreach($DB_TAB as $DB_ROW)
  {
    $tab_matiere[$DB_ROW['rubrique_id']] = array(
      'matiere_nom'         => $DB_ROW['rubrique_nom'],
      'matiere_nb_demandes' => NULL,
    );
  }
}

$item_nb = count($tab_item_infos);
if( !$item_nb && !$make_officiel ) // Dans le cas d’un bilan officiel, où l’on regarde les élèves d’un groupe un à un, ce ne doit pas être bloquant.
{
  Json::end( FALSE , 'Aucun item évalué sur la période '.$date_debut.' ~ '.$date_fin.$precision_socle.$precision_diagnostic.$precision_prof.$precision_niveau.'.' );
}
$tab_liste_item = array_keys($tab_item_infos);
$liste_item = implode(',',$tab_liste_item);

// Liaisons au socle
if( $aff_socle && $type_individuel && $make_html && empty($is_appreciation_groupe) )
{
  $DB_TAB_socle2016 = ($item_nb) ? DB_STRUCTURE_REFERENTIEL::DB_recuperer_socle2016_for_items( $liste_item ) : array() ;
}

// Prendre la bonne référence de l’item
foreach($tab_item_infos as $item_id => $tab)
{
  $tab_item_infos[$item_id][0]['item_ref'] = ($tab[0]['ref_perso']) ? $tab[0]['ref_perso'] : $tab[0]['ref_auto'] ;
  unset( $tab_item_infos[$item_id][0]['ref_perso'] , $tab_item_infos[$item_id][0]['ref_auto'] );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Cas particulier d’un bulletin paramétré avec un affichage au format d’un tableau à double entrée
// ////////////////////////////////////////////////////////////////////////////////////////////////////


if( $make_html && $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') )
{
  Html::$afficher_score = $_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'];
}

if( $make_officiel && empty($is_appreciation_groupe) && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') )
{
  $tab_croisement_synthese = array();
  $tab_croisement_resultat = array();
  $synthese_ref_length = 0;
  foreach($tab_synthese as $synthese_ref => $synthese_nom)
  {
    list($matiere_id_tmp,$synthese_ref_fin) = explode('_',$synthese_ref,2);
    $tab_croisement_resultat[$synthese_ref_fin][$matiere_id_tmp] = TRUE;
    $tab_croisement_synthese[$synthese_ref_fin] = $synthese_nom;
    $synthese_ref_length = max( $synthese_ref_length , mb_strlen($synthese_nom) );
  }
  $nb_format_synthese_differents = count($tab_croisement_synthese);
  if( $nb_format_synthese_differents > 8 )
  {
    $tab_syntheses_uniques = array();
    foreach($tab_croisement_resultat as $synthese_ref_fin => $tab_synthese_matiere)
    {
      if( count($tab_synthese_matiere) == 1 )
      {
        $matiere_id_tmp = key($tab_synthese_matiere);
        $tab_syntheses_uniques[] = $tab_matiere[$matiere_id_tmp]['matiere_nom'].' - '.$tab_croisement_synthese[$synthese_ref_fin];
      }
    }
    Json::end( FALSE , 'Bulletin incompatible avec le format choisi "tableau à double entrée" car il y a '.$nb_format_synthese_differents.' formats de synthèses différents trouvés (8 étant un maximum) ; formats de synthèses orphelins :<br>'.implode('<br>',$tab_syntheses_uniques) );
  }
  // 10 char => 1 hauteur de bloc ; 40 char => 2 hauteurs de blocs
  $synthese_ref_height = max( min( sqrt($synthese_ref_length/10) , 2 ) , 1 );
}

if( $make_html && $make_officiel && empty($is_appreciation_groupe) && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') )
{
  $html_tableau_croise = '<table class="p"><thead><tr><th class="nu"></th>';
  foreach($tab_croisement_synthese as $synthese_ref_fin => $synthese_nom)
  {
    $html_tableau_croise .= '<th class="wpn hc">'.$synthese_nom.'</th>';
  }
  $html_tableau_croise .= '</tr></head><tbody>';
  $emplacement_tableau_croise = 'TABLEAU_CROISE';
}
else
{
  $emplacement_tableau_croise = '';
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Récupération de la liste des élèves
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($_SESSION['USER_PROFIL_TYPE']=='eleve')
{
  $tab_eleve_infos[$_SESSION['USER_ID']] = array(
    'eleve_nom'      => $_SESSION['USER_NOM'],
    'eleve_prenom'   => $_SESSION['USER_PRENOM'],
    'eleve_genre'    => $_SESSION['USER_GENRE'],
    'date_naissance' => $_SESSION['USER_NAISSANCE_DATE'],
    'eleve_INE'      => NULL,
  );
}
elseif(empty($is_appreciation_groupe))
{
  $tab_eleve_infos = DB_STRUCTURE_BILAN::DB_lister_eleves_cibles( $liste_eleve , $groupe_type , $eleves_ordre );
  if(!is_array($tab_eleve_infos))
  {
    Json::end( FALSE , 'Aucun élève trouvé correspondant aux identifiants transmis !' );
  }
}
else
{
  $tab_eleve_infos[0] = array(
    'eleve_nom'      => '',
    'eleve_prenom'   => '',
    'eleve_genre'    => 'I',
    'date_naissance' => NULL,
    'eleve_INE'      => NULL,
  );
}
$eleve_nb = count( $tab_eleve_infos , COUNT_NORMAL );

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Récupération de la liste des résultats des évaluations associées à ces items donnés d’une ou plusieurs matieres donnée(s), pour les élèves selectionnés, sur la période sélectionnée
// Attention, il faut éliminer certains items qui peuvent potentiellement apparaitre dans des relevés d’élèves alors qu’ils n’ont pas été interrogés sur la période considérée (mais un camarade oui).
// ////////////////////////////////////////////////////////////////////////////////////////////////////

$tab_score_a_garder = array();
if($item_nb) // Peut valoir 0 dans le cas d’un bilan officiel où l’on regarde les élèves d’un groupe un à un (il ne faut pas qu’un élève sans rien soit bloquant).
{
  $DB_TAB = DB_STRUCTURE_BILAN::DB_lister_date_last_eleves_items( $liste_eleve , $liste_item , $only_diagnostic );
  foreach($DB_TAB as $DB_ROW)
  {
    $tab_score_a_garder[$DB_ROW['eleve_id']][$DB_ROW['item_id']] = ($DB_ROW['date_last']<$date_sql_debut) ? FALSE : TRUE ;
  }
  $annee_decalage = empty($_SESSION['NB_DEVOIRS_ANTERIEURS']) ? 0 : -1 ;
  $date_sql_debut_annee_scolaire = To::jour_debut_annee_scolaire('sql',$annee_decalage);
  $date_sql_start = Outil::date_sql_start( $retroactif , $date_sql_debut , $date_sql_debut_annee_scolaire );
  $DB_TAB = DB_STRUCTURE_BILAN::DB_lister_result_eleves_items($liste_eleve , $liste_item , $matiere_id , $only_diagnostic , $date_sql_start , $date_sql_fin , $_SESSION['USER_PROFIL_TYPE'] , $only_prof_id , FALSE /*only_valeur*/ , FALSE /*onlynote*/ );
  foreach($DB_TAB as $DB_ROW)
  {
    // test !empty() ajouté car il est arrivé une fois que ce soit indéfini... pas compris pourquoi
    if(!empty($tab_score_a_garder[$DB_ROW['eleve_id']][$DB_ROW['item_id']]))
    {
      if( Outil::is_note_a_garder( $retroactif , $tab_item_infos[$DB_ROW['item_id']][0]['calcul_retroactif'] , $DB_ROW['date'] , $date_sql_debut , $date_sql_debut_annee_scolaire ) )
      {
        $tab_eval[$DB_ROW['eleve_id']][$DB_ROW['item_id']][] = array(
          'note' => $DB_ROW['note'],
          'date' => $DB_ROW['date'],
          'info' => $DB_ROW['info'],
        );
      }
    }
  }
}
if( !count($tab_eval) && !$make_officiel ) // Dans le cas d’un bilan officiel, où l’on regarde les élèves d’un groupe un à un, ce ne doit pas être bloquant.
{
  Json::end( FALSE , 'Aucune évaluation trouvée sur la période '.$date_debut.' ~ '.$date_fin.$precision_socle.$precision_diagnostic.$precision_prof.$precision_niveau.'.' );
}

// Liste des matières d’un prof
$listing_prof_matieres_id = ( !$make_officiel && $type_individuel && ($_SESSION['USER_PROFIL_TYPE']=='professeur') ) ? DB_STRUCTURE_COMMUN::DB_recuperer_matieres_professeur($_SESSION['USER_ID']) : '' ;
$tab_prof_matieres_id = !empty($listing_prof_matieres_id) ? explode(',',$listing_prof_matieres_id) : array() ;

// ////////////////////////////////////////////////////////////////////////////////////////////////////
/* 
 * Libérer de la place mémoire car les scripts de bilans sont assez gourmands.
 * Supprimer $DB_TAB ne fonctionne pas si on ne force pas auparavant la fermeture de la connexion.
 * SebR devrait peut-être envisager d’ajouter une méthode qui libère cette mémoire, si c’est possible...
 */
// ////////////////////////////////////////////////////////////////////////////////////////////////////

DB::close(SACOCHE_STRUCTURE_BD_NAME);
unset($DB_TAB);

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Tableaux et variables pour mémoriser les infos ; dans cette partie on ne fait que les calculs (aucun affichage)
// ////////////////////////////////////////////////////////////////////////////////////////////////////

$tab_score_eleve_item      = array();  // Retenir les scores / élève / matière / synthese / item
$tab_infos_acquis_eleve    = array();  // Retenir les infos (nb acquis) / élève / matière / synthèse + total
$tab_infos_detail_synthese = array();  // Retenir le détail du contenu d’une synthèse / élève / synthèse
$tab_synthese_indicateur   = array();  // Retenir le pourcentage de synthèse / élève / matière / synthese
$tab_rubriques             = array();  // Retenir les synthèses par matière (pour le tableau de synthèse)

/*
  On renseigne :
  $tab_score_eleve_item[$eleve_id][$matiere_id][$synthese_ref][$item_id]
  $tab_infos_acquis_eleve[$eleve_id][$matiere_id]
  $tab_rubriques[$matiere_id][$synthese_ref]
*/

// Pour chaque élève...
if(empty($is_appreciation_groupe))
{
  // Pour un relevé officiel, on force les droits du profil parent pour le PDF, mais pas pour le détail HTML, non imprimé.
  $forcer_profil = NULL ;
  $afficher_score = Outil::test_user_droit_specifique( $_SESSION['DROIT_VOIR_SCORE_BILAN'] , NULL /*matiere_coord_or_groupe_pp_connu*/ , 0 /*matiere_id_or_groupe_id_a_tester*/ , $forcer_profil );
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    // Si cet élève a été évalué...
    if(isset($tab_eval[$eleve_id]))
    {
      // Pour chaque item on calcule son score bilan, et on mémorise les infos pour le détail HTML
      foreach($tab_eval[$eleve_id] as $item_id => $tab_devoirs)
      {
        // le score bilan
        extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $matiere_id $calcul_methode $calcul_limite $calcul_retroactif $synthese_ref
        $matiere_nb_demandes = $tab_matiere[$matiere_id]['matiere_nb_demandes'];
        $score = OutilBilan::calculer_score( $tab_devoirs , $calcul_methode , $calcul_limite , $date_sql_debut ) ;
        $tab_score_eleve_item[$eleve_id][$matiere_id][$synthese_ref][$item_id] = $score;
        // le détail HTML
        if($make_html)
        {
          if( ($score!==FALSE) || $aff_prop_sans_score )
          {
            $indice = OutilBilan::determiner_etat_acquisition( $score );
            if($aff_coef)
            {
              $texte_coef = '[×'.$item_coef.'] ';
            }
            if($aff_socle)
            {
              $socle_nb = !isset($DB_TAB_socle2016[$item_id]) ? 0 : count($DB_TAB_socle2016[$item_id]) ;
              $texte_s2016 = (!$socle_nb) ? '[–] ' : ( ($socle_nb>1) ? '['.$socle_nb.'c.] ' : '['.($DB_TAB_socle2016[$item_id][0]['composante']/10).'] ' ) ;
            }
            if($aff_lien)
            {
              $texte_lien_avant = ($item_lien) ? '<a target="_blank" rel="noopener noreferrer" href="'.html($item_lien).'">' : '';
              $texte_lien_apres = ($item_lien) ? '</a>' : '';
            }
            $icones_action = ( ($_SESSION['USER_PROFIL_TYPE']=='professeur') && !$make_officiel && in_array($matiere_id,$tab_prof_matieres_id) )
                           ? '<q class="ajouter_note"'.infobulle('Ajouter une évaluation à la volée.').'></q>'
                           . '<q class="modifier_note"'.infobulle('Modifier à la volée une saisie d’évaluation.').'></q>'
                           : '' ;
            if($aff_panier)
            {
              $debut_date = isset($tab_devoirs[0]) ? $tab_devoirs[0]['date'] : '' ;
              if(!$matiere_nb_demandes) { $icones_action .= '<q class="demander_non"'.infobulle('Pas de demande autorisée pour les items de cette matière.').'></q>'; }
              elseif(!$item_cart)       { $icones_action .= '<q class="demander_non"'.infobulle('Pas de demande autorisée pour cet item précis.').'></q>'; }
              else                      { $icones_action .= '<q class="demander_add" data-score="'.( $score ? $score : -1 ).'" data-date="'.$debut_date.'"'.infobulle('Ajouter aux demandes d’évaluations.').'></q>'; }
            }
            if($score!==FALSE)
            {
              $pourcentage = ($afficher_score) ? $score.'%' : '&nbsp;' ;
              $span_pourcentage = '<span class="pourcentage A'.$indice.'">'.$pourcentage.'</span> ';
            }
            else if($aff_prop_sans_score)
            {
              $span_pourcentage = '<span class="pourcentage">&nbsp;</span> ';
            }
            $tab_infos_detail_synthese[$eleve_id][$synthese_ref][] = '<div data-matiere="'.$matiere_id.'" data-item="'.$item_id.'" data-eleve="'.$eleve_id.'">'.$span_pourcentage.$texte_coef.$texte_s2016.$texte_lien_avant.html($item_ref.' - '.$item_nom).$texte_lien_apres.$icones_action.'</div>';
          }
        }
      }
      // Pour chaque élément de synthèse, et pour chaque matière on recense le nombre d’items considérés acquis ou pas
      if( $type_individuel || ( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='classique') ) )
      {
        foreach($tab_score_eleve_item[$eleve_id] as $matiere_id => $tab_matiere_scores)
        {
          foreach($tab_matiere_scores as $synthese_ref => $tab_synthese_scores)
          {
            $tableau_score_filtre = ($aff_prop_sans_score) ? $tab_synthese_scores : array_filter($tab_synthese_scores,'non_vide');
            $nb_scores = count( $tableau_score_filtre );
            if(!isset($tab_infos_acquis_eleve[$eleve_id][$matiere_id]))
            {
              // Le mettre avant le test sur $nb_scores permet d’avoir au moins le titre des matières où il y a des saisies mais seulement AB NN etc. (et donc d’avoir la rubrique sur le bulletin).
              $tab_infos_acquis_eleve[$eleve_id][$matiere_id]['total'] = array_fill_keys( array_keys($_SESSION['ACQUIS']) , 0 );
              if($aff_prop_sans_score)
              {
                $tab_infos_acquis_eleve[$eleve_id][$matiere_id]['total'][0] = 0;
              }
            }
            if($nb_scores)
            {
              $tab_infos_acquis_eleve[$eleve_id][$matiere_id][$synthese_ref] = OutilBilan::compter_nombre_acquisitions_par_etat( $tableau_score_filtre , $aff_prop_sans_score );
              foreach( $tab_infos_acquis_eleve[$eleve_id][$matiere_id][$synthese_ref] as $acquis_id => $acquis_nb )
              {
                $tab_infos_acquis_eleve[$eleve_id][$matiere_id]['total'][$acquis_id] += $acquis_nb;
              }
            }
          }
        }
      }
      // Pour chaque élément de synthèse, et pour chaque matière on recense la moyenne des pourcentages ou le pourcentage d’items acquis
      if( $type_synthese || ( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') ) )
      {
        foreach($tab_score_eleve_item[$eleve_id] as $matiere_id => $tab_matiere_scores)
        {
          $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] = array
          (
            'somme_scores_coefs'   => 0 ,
            'somme_scores_simples' => 0 ,
            'nb_coefs'             => 0 ,
            'nb_scores'            => 0 ,
          ) + array_fill_keys( array_keys($_SESSION['ACQUIS']) , 0 );
          foreach($tab_matiere_scores as $synthese_ref => $tab_synthese_scores)
          {
            $tab_rubriques[$matiere_id][$synthese_ref] = $tab_synthese[$synthese_ref];
            // calcul des bilans des scores
            $tableau_score_filtre = array_filter($tab_synthese_scores,'non_vide');
            $nb_scores = count( $tableau_score_filtre );
            // Si indicateur "Moyenne des pourcentages d’acquisition"
            if( $synthese_indicateur == 'moyenne_pourcentages' )
            {
              // la moyenne peut être pondérée par des coefficients
              $somme_scores_ponderes = 0;
              $somme_coefs = 0;
              if($nb_scores)
              {
                foreach($tableau_score_filtre as $item_id => $item_score)
                {
                  $somme_scores_ponderes += $item_score*$tab_item_infos[$item_id][0]['item_coef'];
                  $somme_coefs += $tab_item_infos[$item_id][0]['item_coef'];
                }
                $somme_scores_simples = array_sum($tableau_score_filtre);
                // pour le total par matière
                $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['somme_scores_coefs']   += $somme_scores_ponderes;
                $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['somme_scores_simples'] += $somme_scores_simples;
                $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_coefs']             += $somme_coefs;
                $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores']            += $nb_scores;
              }
              if($with_coef) { $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] = ($somme_coefs) ? round($somme_scores_ponderes/$somme_coefs,0) : FALSE ; }
              else           { $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] = ($nb_scores)   ? round($somme_scores_simples/$nb_scores,0)    : FALSE ; }
            }
            // Si indicateur "Pourcentage d’items acquis"
            if( $synthese_indicateur == 'pourcentage_acquis' )
            {
              if($nb_scores)
              {
                $tab_acquisitions = OutilBilan::compter_nombre_acquisitions_par_etat( $tableau_score_filtre , 0 /*aff_prop_sans_score*/ );
                $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] = OutilBilan::calculer_pourcentage_acquisition_items( $tab_acquisitions , $nb_scores );
                // pour le total par matière
                $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores'] += $nb_scores;
                foreach( $tab_acquisitions as $acquis_id => $acquis_nb )
                {
                  $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'][$acquis_id] += $acquis_nb;
                }
              }
              else
              {
                $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] = FALSE;
              }
            }
          }
          // Total pour la matière
          if( $synthese_indicateur == 'moyenne_pourcentages' )
          {
            if($with_coef) { $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] = ($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_coefs'])  ? round($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['somme_scores_coefs']  /$tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_coefs'] ,0) : FALSE ; }
            else           { $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] = ($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores']) ? round($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['somme_scores_simples']/$tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores'],0) : FALSE ; }
          }
          if( $synthese_indicateur == 'pourcentage_acquis' )
          {
            $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] = ($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores']) ? OutilBilan::calculer_pourcentage_acquisition_items( $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] , $tab_synthese_indicateur[$eleve_id][$matiere_id]['total']['nb_scores'] ) : FALSE ;
          }
        }
      }
    }
  }
}
else
{
  // Pour pouvoir passer dans la boucle en cas d’appréciation sur le groupe
  foreach($tab_matiere as $matiere_id => $tab)
  {
    $tab_infos_acquis_eleve[$eleve_id][$matiere_id]['total'] = array_fill_keys( array_keys($_SESSION['ACQUIS']) , 0 );
  }
}

$matiere_nb  = count($tab_rubriques);
$rubrique_nb = count($tab_rubriques, COUNT_RECURSIVE) - $matiere_nb;

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Compter le nombre de lignes à afficher par élève par matière
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($make_pdf)
{

  $tab_nb_lignes = array();
  $nb_lignes_appreciation_generale_avec_intitule = ( $make_officiel && $_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_GENERALE_LONGUEUR'] ) ? 1+max(6,$_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_GENERALE_LONGUEUR']/100) : 0 ;
  $nb_lignes_assiduite                           = ( $make_officiel && ($affichage_assiduite) )                                           ? 1.3 : 0 ;
  $nb_lignes_prof_principal                      = ( $make_officiel && ($affichage_prof_principal) )                                      ? 1.3 : 0 ;
  $nb_lignes_supplementaires                     = ( $make_officiel && $_SESSION['OFFICIEL']['BULLETIN_LIGNE_SUPPLEMENTAIRE'] )           ? 1.3 : 0 ;
  $nb_lignes_legendes                            = ($legende=='oui') ? 0.5 + 1 : 0 ;
  $nb_lignes_matiere_marge    = 1 ;
  $nb_lignes_matiere_intitule = 2 ;
  $nb_lignes_matiere_intitule_et_marge = $nb_lignes_matiere_marge + $nb_lignes_matiere_intitule ;

  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    foreach($tab_matiere as $matiere_id => $tab)
    {
      if(isset($tab_score_eleve_item[$eleve_id][$matiere_id]))
      {
        // Ne pas compter les lignes de synthèses dont aucun item n’a été évalué
        if(!$aff_prop_sans_score)
        {
          foreach($tab_score_eleve_item[$eleve_id][$matiere_id] as $synthese_ref => $tab_items)
          {
            $nb_items_evalues = count(array_filter($tab_items,'non_vide'));
            if(!$nb_items_evalues)
            {
              unset($tab_score_eleve_item[$eleve_id][$matiere_id][$synthese_ref]);
            }
          }
        }
        // Compter la longueur de chaque appréciation
        $nb_lignes_appreciation_intermediaire = 0;
        if(isset($tab_saisie[$eleve_id][$matiere_id]))
        {
          foreach($tab_saisie[$eleve_id][$matiere_id] as $prof_id => $tab)
          {
            if($prof_id) // Sinon c’est la note.
            {
              $nb_lignes_appreciation_intermediaire += max( 2 , ceil(strlen($tab['appreciation'])/100) , min( substr_count($tab['appreciation'],"\n") + 1 , $_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR'] / 100 ) );
            }
          }
        }
        $nb_lignes_rubriques = count($tab_score_eleve_item[$eleve_id][$matiere_id]) ;
        $nb_lignes_appreciations = ( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR']) && (isset($tab_saisie[$eleve_id][$matiere_id])) ) ? $nb_lignes_appreciation_intermediaire + 1 : 0 ; // + 1 pour "Appréciation / Conseils pour progresser"
        if( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') )
        {
        // On fait comme si la hauteur dépendait des matières même si au final on comptera la même pour chacune (en en prenant la moyenne).
          $tab_nb_lignes[$eleve_id][$matiere_id] = max($nb_lignes_rubriques,$nb_lignes_appreciations) ;
        }
        else
        {
          $tab_nb_lignes[$eleve_id][$matiere_id] = $nb_lignes_matiere_intitule_et_marge + max($nb_lignes_rubriques,$nb_lignes_appreciations) ;
        }
      }
    }
  }

  // Calcul des totaux une unique fois par élève
  $tab_nb_lignes_total_synthese_eleve = array();
  $tab_nb_blocs_tableau_croise_eleve  = array();
  foreach($tab_nb_lignes as $eleve_id => $tab)
  {
    if( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') )
    {
      $nb_matieres = count($tab);
      $nb_lignes_moyen_par_matiere = ($nb_matieres) ? array_sum($tab) / $nb_matieres : 0 ;
      // On compte la 1ère ligne du tableau à double entrée avec les nom des synthèse à la verticale comme $synthese_ref_height hauteurs de matières.
      $tab_nb_blocs_tableau_croise_eleve[ $eleve_id] = $nb_matieres + $synthese_ref_height;
      $tab_nb_lignes_total_synthese_eleve[$eleve_id] = $nb_lignes_matiere_marge + $nb_lignes_moyen_par_matiere * $tab_nb_blocs_tableau_croise_eleve[$eleve_id];
    }
    else
    {
      $tab_nb_lignes_total_synthese_eleve[$eleve_id] = array_sum($tab);
      $tab_nb_blocs_tableau_croise_eleve[ $eleve_id] = NULL;
    }
  }
  $nb_lignes_total_synthese = array_sum($tab_nb_lignes_total_synthese_eleve);

}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Nombre de boucles par élève (entre 1 et 3 pour les bilans officiels, dans ce cas $tab_destinataires[] est déjà complété ; une seule dans les autres cas).
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if(!isset($tab_destinataires))
{
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    $tab_destinataires[$eleve_id][0] = TRUE ;
  }
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Elaboration du bilan individuel de la synthèse matière ou multi-matières, en HTML et PDF
// ////////////////////////////////////////////////////////////////////////////////////////////////////

$affichage_direct = ( ( ( in_array($_SESSION['USER_PROFIL_TYPE'],array('eleve','parent')) ) && (SACoche!='webservices') ) || ($make_officiel) ) ? TRUE : FALSE ;

if($type_individuel)
{
  // Préparatifs
  $tab_graph_data = array();
  if( ($make_html) || ($make_graph) )
  {
    $bouton_print_test = (isset($is_bouton_test_impression))                  ? ( ($is_bouton_test_impression) ? ' <button id="simuler_impression" type="button" class="imprimer">Simuler l’impression finale de ce bilan</button>' : ' <button id="simuler_disabled" type="button" class="imprimer" disabled>Pour simuler l’impression, sélectionner un élève</button>' ) : '' ;
    $bouton_import_csv = in_array($make_action,array('modifier','tamponner')) ? ' <button id="saisir_deport" type="button" class="fichier_export">Saisie déportée</button>'                         : '' ;
    $info_details      = (!$make_graph)                                       ? 'Cliquer sur <span class="toggle_plus"></span> / <span class="toggle_moins"></span> pour afficher / masquer le détail (<a href="#" id="montrer_details">tout montrer</a>).' : '' ;
    $html  = $affichage_direct ? '' : '<style>'.$_SESSION['CSS'].'</style>'.NL;
    $html .= $make_officiel    ? '' : '<h1>Synthèse '.$tab_titre[$synthese_modele].'</h1>'.NL;
    $html .= $make_officiel    ? '' : '<h2>'.html($texte_periode).'<br>'.$texte_precision_html.'</h2>'.NL;
    $html .= (!$make_graph) ? '<div class="astuce">'.$info_details.$bouton_print_test.$bouton_import_csv.'</div>'.NL.$emplacement_tableau_croise : '<div id="div_graphique_officiel"></div>'.NL ;
    $separation = (count($tab_eleve_infos)>1) ? '<hr class="breakafter">'.NL : '' ;
    // Légende identique pour tous les élèves car pas de codes de notation donc pas de codages spéciaux.
    $legende_html = ($legende=='oui') ? Html::legende( array('etat_acquisition'=>TRUE,'aff_prop_sans_score'=>$aff_prop_sans_score) ) : '' ;
    $width_barre = (!$make_officiel) ? 180 : 50 ;
    $width_texte = 900 - $width_barre;
  }
  if($make_pdf)
  {
    $pdf = new PDF_item_synthese( $make_officiel , 'A4' /*page_size*/ , 'portrait' /*orientation*/ , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond , $legende , !empty($is_test_impression) /*filigrane*/ );
    $pdf->initialiser( $synthese_modele , $nb_lignes_total_synthese , $eleve_nb );
    if($make_officiel)
    {
      $tab_archive['user'][0][] = array( '__construct' , array( $make_officiel , 'A4' /*page_size*/ , 'portrait' /*orientation*/ , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , 'oui' /*couleur*/ , $fond , $legende , !empty($is_test_impression) /*filigrane*/ , $tab_archive['session'] ) );
    }
  }
  // Pour chaque élève...
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    extract($tab_eleve);  // $eleve_INE $eleve_nom $eleve_prenom $eleve_genre $date_naissance
    $eleve_nom_prenom = To::texte_eleve_identite($eleve_nom,$eleve_prenom,$eleves_ordre);
    $date_naissance = ($date_naissance) ? To::date_sql_to_french($date_naissance) : '' ;
    if($make_officiel)
    {
      // Quelques variables récupérées ici car pose pb si placé dans la boucle par destinataire
      $moyenne_generale_eleve_enregistree  = isset($tab_saisie[$eleve_id][0][0]['note']) ? $tab_saisie[$eleve_id][0][0]['note'] : NULL ;
      $moyenne_generale_classe_enregistree = isset($tab_saisie[0][0][0]['note']) ? $tab_saisie[0][0][0]['note'] : NULL ;
      unset($tab_saisie[$eleve_id][0][0]);
      $is_appreciation_generale_enregistree = (empty($tab_saisie[$eleve_id][0])) ? FALSE : TRUE ;
      $prof_id_appreciation_generale = ($is_appreciation_generale_enregistree) ?     key($tab_saisie[$eleve_id][0]) : 0 ;
      $tab_appreciation_generale     = ($is_appreciation_generale_enregistree) ? current($tab_saisie[$eleve_id][0]) : array('prof_info'=>'','appreciation'=>'') ;
    }
    foreach($tab_destinataires[$eleve_id] as $numero_tirage => $tab_adresse)
    {
      $is_archive = ( ($make_officiel) && ($numero_tirage==0) && empty($is_test_impression) ) ? TRUE : FALSE ;
      // Si cet élève a été évalué...
      if(isset($tab_infos_acquis_eleve[$eleve_id]))
      {
        // Intitulé
        if($make_html) { $html .= (!$make_officiel) ? $separation.'<h2>'.html($groupe_nom.' - '.$eleve_nom_prenom).'</h2>'.NL : '' ; }
        if($make_pdf)
        {
          if($is_archive)
          {
            $tab_archive['user'][$eleve_id]['image_md5'] = array();
            $tab_archive['user'][$eleve_id][] = array( 'initialiser' , array( $synthese_modele , $tab_nb_lignes_total_synthese_eleve[$eleve_id] , 1 /*eleve_nb*/ ) );
          }
          $eleve_nb_lignes_hors_synthese = $nb_lignes_appreciation_generale_avec_intitule + $nb_lignes_assiduite + $nb_lignes_prof_principal + $nb_lignes_supplementaires;
          $eleve_nb_lignes = $tab_nb_lignes_total_synthese_eleve[$eleve_id] + $eleve_nb_lignes_hors_synthese;
          $tab_infos_entete = (!$make_officiel) ?
            array(
              'bilan_titre'     => $tab_titre[$synthese_modele] ,
              'texte_periode'   => $texte_periode ,
              'texte_precision' => $texte_precision_pdf_csv ,
              'groupe_nom'      => $groupe_nom ,
            ) :
            array(
              'tab_etabl_coords'          => $tab_etabl_coords ,
              'tab_etabl_logo'            => $tab_etabl_logo ,
              'etabl_coords_bloc_hauteur' => $etabl_coords_bloc_hauteur ,
              'tab_bloc_titres'           => $tab_bloc_titres ,
              'tab_adresse'               => $tab_adresse ,
              'tag_date_heure_initiales'  => $tag_date_heure_initiales ,
              'eleve_genre'               => $eleve_genre ,
              'date_naissance'            => $date_naissance ,
            ) ;
          $tab_infos_croisement = ( $make_officiel && ($_SESSION['OFFICIEL']['BULLETIN_FORMAT']=='croisement') ) ?
            array(
              'eleve_nb_blocs'                => $tab_nb_blocs_tableau_croise_eleve[$eleve_id] ,
              'eleve_nb_lignes_hors_synthese' => $eleve_nb_lignes_hors_synthese ,
            ) :
            NULL ;
          $pdf->entete( $tab_infos_entete , $eleve_nom_prenom , $eleve_INE , $eleve_nb_lignes , $tab_infos_croisement );
          if($is_archive)
          {
            if(!empty($tab_etabl_logo))
            {
              // On remplace l’image par son md5
              $image_contenu = $tab_etabl_logo['contenu'];
              $image_md5     = md5($image_contenu);
              $tab_archive['image'][$image_md5] = $image_contenu;
              $tab_archive['user'][$eleve_id]['image_md5'][] = $image_md5;
              $tab_infos_entete['tab_etabl_logo']['contenu'] = $image_md5;
            }
            $tab_archive['user'][$eleve_id][] = array( 'entete' , array( $tab_infos_entete , $eleve_nom_prenom , $eleve_INE , $eleve_nb_lignes , $tab_infos_croisement ) );
          }
          if(!is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]))
          {
            $pdf->ligne_tableau_entete( $tab_croisement_synthese , $nb_format_synthese_differents , $synthese_ref_height );
            if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_tableau_entete' , array( $tab_croisement_synthese , $nb_format_synthese_differents , $synthese_ref_height ) ); }
          }
        }
        // On passe en revue les matières...
        foreach($tab_infos_acquis_eleve[$eleve_id] as $matiere_id => $tab_infos_matiere)
        {
          $matiere_nom = $tab_matiere[$matiere_id]['matiere_nom'];
          if( (!$make_officiel) || ($make_action=='tamponner') || (($make_action=='modifier')&&(in_array($matiere_id,$tab_matiere_id))) || (($make_action=='examiner')&&(in_array($matiere_id,$tab_matiere_id))) || ($make_action=='consulter') || ($make_action=='imprimer') )
          {
            // On a besoin de savoir maintenant s’il y a une appréciation qui sera écrite et sinon si on peut occuper toute la largeur, donc test avancé ici...
            $sans_cadre_appreciation = ( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_VIDE_CACHE']) && ( !$_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR'] || !isset($tab_saisie[$eleve_id][$matiere_id]) || !max(array_keys($tab_saisie[$eleve_id][$matiere_id])) ) ) ? TRUE : FALSE ;
            // Bulletin - Interface graphique
            if( $make_graph )
            {
              $tab_graph_data['categories'][$matiere_id] = '"'.addcslashes($matiere_nom,'"').'"';
              foreach( $_SESSION['ACQUIS'] as $acquis_id => $tab_acquis_info )
              {
                $tab_graph_data['series_data_'.$acquis_id][$matiere_id] = $tab_infos_matiere['total'][$acquis_id];
              }
              if($eleve_id && $aff_prop_sans_score)
              {
                $tab_graph_data['series_data_0'][$matiere_id] = $tab_infos_matiere['total'][0];
              }
              if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
              {
                if($eleve_id) // Si appréciation sur le groupe alors pas de courbe élève
                {
                  $note = isset($tab_saisie[$eleve_id][$matiere_id][0]) ? $tab_saisie[$eleve_id][$matiere_id][0]['note'] : NULL ;
                  $tab_graph_data['series_data_MoyEleve'][$matiere_id] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : round($note*5) ) : 'null' ;
                  // Périodes précédentes pour information
                  foreach($tab_periode_avant as $periode_id => $periode_nom)
                  {
                    $note = isset($tab_saisie_avant[$eleve_id][$matiere_id][$periode_id][0]) ? $tab_saisie_avant[$eleve_id][$matiere_id][$periode_id][0]['note'] : NULL ;
                    $tab_graph_data['series_data_periode'.$periode_id][$matiere_id] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : round($note*5) ) : 'null' ;
                  }
                }
                if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
                {
                  $note = isset($tab_saisie[0][$matiere_id][0]) ? $tab_saisie[0][$matiere_id][0]['note'] : NULL ;
                  $tab_graph_data['series_data_MoyClasse'][$matiere_id] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : round($note*5) ) : 'null' ;
                  // Périodes précédentes pour information
                  if( !$eleve_id )
                  {
                    foreach($tab_periode_avant as $periode_id => $periode_nom)
                    {
                      $note = isset($tab_saisie_avant[0][$matiere_id][$periode_id][0]) ? $tab_saisie_avant[0][$matiere_id][$periode_id][0]['note'] : NULL ;
                      $tab_graph_data['series_data_periode'.$periode_id][$matiere_id] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : round($note*5) ) : 'null' ;
                    }
                  }
                }
              }
            }
            $tab_infos_matiere['total'] = array_filter($tab_infos_matiere['total'],'non_zero'); // Retirer les valeurs nulles
            $total = array_sum($tab_infos_matiere['total']) ; // La somme ne peut être nulle, sinon la matière ne se serait pas affichée
            if($make_pdf)
            {
              $moyenne_eleve  = NULL;
              $moyenne_classe = NULL;
              if( ($make_officiel) && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) && isset($tab_saisie[$eleve_id][$matiere_id][0]) )
              {
                // $tab_saisie[$eleve_id][$matiere_id][0] est normalement toujours défini : soit calculé lors de l’initialisation du bulletin, soit effacé et non recalculé volontairement mais alors vaut NULL (à moins que le choix de l’affichage d’une moyenne se fasse simultanément)
                extract($tab_saisie[$eleve_id][$matiere_id][0]);  // $prof_info $appreciation $note
                $moyenne_eleve = $note;
                if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
                {
                  $moyenne_classe = $tab_saisie[0][$matiere_id][0]['note'];
                }
              }
              if(is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]))
              {
                $pdf->ligne_matiere( $matiere_nom , $tab_nb_lignes[$eleve_id][$matiere_id] , $tab_infos_matiere['total'] , $total , $moyenne_eleve , $moyenne_classe , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation );
                if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_matiere' , array( $matiere_nom , $tab_nb_lignes[$eleve_id][$matiere_id] , $tab_infos_matiere['total'] , $total , $moyenne_eleve , $moyenne_classe , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation ) ); }
              }
            }
            if($make_html)
            {
              $html .= '<table class="bilan" style="width:900px;margin-bottom:0"><tbody>'.NL.'<tr>';
              if(empty($html_tableau_croise))
              {
                $html .= '<th style="width:540px">'.html($matiere_nom).'</th>';
                $html .= ( !$make_officiel || $_SESSION['OFFICIEL']['BULLETIN_BARRE_ACQUISITIONS'] ) ? Html::td_barre_synthese($width=360,$tab_infos_matiere['total'],$total,$avec_texte_nombre,$avec_texte_code) : '<td style="width:360px"></td>' ;
              }
              else
              {
                $html .= '<th>'.html($matiere_nom).'</th>';
                $html_tableau_croise .= '<tr><th class="wpn">'.html($matiere_nom).'</th>';
              }
              $html .= '</tr>'.NL.'</tbody></table>'; // Utilisation de 2 tableaux sinon bugs constatés lors de l’affichage des détails...
              $html .= '<table class="bilan" style="width:900px;margin-top:0"><tbody>'.NL;
            }
            //  On passe en revue les synthèses...
            unset($tab_infos_matiere['total']);
            $nb_syntheses = count($tab_infos_matiere);

            if($nb_syntheses)
            {
              $hauteur_ligne_synthese = ( ($make_officiel) && ($make_pdf) ) ? ( $tab_nb_lignes[$eleve_id][$matiere_id] - $nb_lignes_matiere_intitule_et_marge ) / count($tab_infos_matiere) : 1 ;
              foreach($tab_infos_matiere as $synthese_ref => $tab_infos_synthese)
              {
                $tab_infos_synthese = array_filter($tab_infos_synthese,'non_zero'); // Retirer les valeurs nulles
                $total = array_sum($tab_infos_synthese) ; // La somme ne peut être nulle (sinon la matière ne se serait pas affichée)
                if( $make_pdf && is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]) )
                {
                  $pdf->ligne_synthese( $tab_synthese[$synthese_ref] , $tab_infos_synthese , $total , $hauteur_ligne_synthese , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation );
                  if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_synthese' , array( $tab_synthese[$synthese_ref] , $tab_infos_synthese , $total , $hauteur_ligne_synthese , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation  ) ); }
                }
                if($make_html)
                {
                  if(empty($html_tableau_croise))
                  {
                    $html .= '<tr>';
                    $html .= Html::td_barre_synthese($width_barre,$tab_infos_synthese,$total,$avec_texte_nombre,$avec_texte_code);
                    $html .= '<td style="width:'.$width_texte.'px">' ;
                    $html .= '<a href="#toggle" class="'.$toggle_class.'"'.infobulle('Voir / masquer le détail des items associés.').' id="to_'.$eleve_id.'_'.$synthese_ref.'"></a> ';
                    $html .= html($tab_synthese[$synthese_ref]);
                    $html .= '<div id="'.$eleve_id.'_'.$synthese_ref.'"'.$toggle_etat.'>'.implode('',$tab_infos_detail_synthese[$eleve_id][$synthese_ref]).'</div>';
                    $html .= '</td></tr>'.NL;
                  }
                }
              }
            }
            elseif( $make_officiel && $make_pdf && is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]) )
            {
              // Il est possible qu’aucun item n’ait été évalué pour un élève (absent...) : il faut quand même dessiner un cadre pour ne pas provoquer un décalage, d’autant plus qu’il peut y avoir une appréciation à côté.
              $hauteur_ligne_synthese = $tab_nb_lignes[$eleve_id][$matiere_id] - $nb_lignes_matiere_intitule_et_marge ;
              $pdf->ligne_synthese( '' , array() , 0 , $hauteur_ligne_synthese , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation );
              if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_synthese' , array( '' , array() , 0 , $hauteur_ligne_synthese , $avec_texte_nombre , $avec_texte_code , $sans_cadre_appreciation ) ); }
            }
            if($make_html)
            {
              if(!empty($html_tableau_croise))
              {
                foreach($tab_croisement_synthese as $synthese_ref_fin => $synthese_nom)
                {
                  $synthese_ref = $matiere_id.'_'.$synthese_ref_fin;
                  $score = isset($tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref]) ? $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] : FALSE ;
                  $detail = ($score===FALSE) ? '' : '<a href="#toggle" class="'.$toggle_class.'"'.infobulle('Voir / masquer le détail des items associés.').' id="to_'.$eleve_id.'_'.$synthese_ref.'"></a>'.'<div id="'.$eleve_id.'_'.$synthese_ref.'"'.$toggle_etat.'>'.implode('',$tab_infos_detail_synthese[$eleve_id][$synthese_ref]).'</div>' ;
                  $html_tableau_croise .= str_replace( array('<td class="','</td>') , array('<td class="wpn ','&nbsp;'.$detail.'</td>') , Html::td_score($score,'','%','',FALSE) );
                }
                $html_tableau_croise .= '</tr>';
              }
              // Bulletin - Info saisies périodes antérieures
              if( ($make_html) && ($make_officiel) && (isset($tab_saisie_avant[$eleve_id][$matiere_id])) )
              {
                $tab_periode_liens  = array();
                $tab_periode_textes = array();
                foreach($tab_saisie_avant[$eleve_id][$matiere_id] as $periode_id => $tab_prof)
                {
                  $tab_ligne = array(0=>''); // Pour forcer la note à être le 1er indice ; sert aussi à indiquer la période.
                  foreach($tab_prof as $prof_id => $tab)
                  {
                    extract($tab);  // $prof_info $appreciation $note
                    if(!$prof_id) // C’est la note.
                    {
                      if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
                      {
                        $tab_ligne[0] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : ($note*5).'&nbsp;%' ) : '-' ;
                      }
                    }
                    else
                    {
                      $tab_ligne[$prof_id] = html('['.$prof_info.'] '.$appreciation);
                    }
                  }
                  $tab_ligne[0] = '<b>'.html($tab_periode_avant[$periode_id]).'&nbsp;:&nbsp;'.$tab_ligne[0].'</b>';
                  $tab_periode_liens[]  = '<a href="#toggle" class="toggle_plus"'.infobulle('Voir / masquer les informations de cette période.').' id="to_'.$eleve_id.'_avant_'.$matiere_id.'_'.$periode_id.'"></a> '.html($tab_periode_avant[$periode_id]);
                  $tab_periode_textes[] = '<div id="'.$eleve_id.'_avant_'.$matiere_id.'_'.$periode_id.'" class="appreciation bordertop hide">'.implode('<br>',$tab_ligne).'</div>';
                }
                $html .= '<tr><td colspan="2" class="avant">'.implode('&nbsp;&nbsp;&nbsp;',$tab_periode_liens).implode('',$tab_periode_textes).'</td></tr>'.NL;
              }
              // Bulletin - Note (HTML)
              if( ($make_html) && ($make_officiel) && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) && ( $_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'] || $eleve_id ) && isset($tab_saisie[$eleve_id][$matiere_id][0]) && !in_array($matiere_id,$tab_moyenne_exception_matieres) )
              {
                // $tab_saisie[$eleve_id][$matiere_id][0] est normalement toujours défini car déjà calculé (mais peut valoir NULL)
                extract($tab_saisie[$eleve_id][$matiere_id][0]);  // $prof_info $appreciation $note
                // infobulle non placée sur les éléments button car ne s’applique pas si attribut disabled (https://api.jqueryui.com/tooltip/)
                $infobulle   = ( $BILAN_ETAT <= $_SESSION['OFFICIEL']['BULLETIN_ETAPE_MAX_MAJ_POSITIONNEMENTS'] ) ? '' : infobulle('Modification des positionnements interdite par la configuration de ce bulletin.') ;
                $bouton_etat = ( $BILAN_ETAT <= $_SESSION['OFFICIEL']['BULLETIN_ETAPE_MAX_MAJ_POSITIONNEMENTS'] ) ? '' : ' disabled' ;
                $bouton_nettoyer  = ($appreciation!='') ? ' <button type="button" class="nettoyer"'.$bouton_etat.'>Effacer et recalculer.</button>' : '' ;
                $bouton_supprimer = ($note!==NULL)      ? ' <button type="button" class="supprimer"'.$bouton_etat.'>Supprimer sans recalculer</button>' : '' ;
                $note = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : ($note*5).'&nbsp;%' ) : '-' ;
                $appreciation = ($appreciation!='') ? $appreciation : ( ($eleve_id) ? 'Moyenne calculée / reportée / actualisée automatiquement.' : 'Moyenne de classe (calculée / actualisée automatiquement).' ) ;
                $action = ( ($make_action=='modifier') && ($eleve_id) ) ? ' <button type="button" class="modifier"'.$bouton_etat.'>Modifier</button>'.$bouton_nettoyer.$bouton_supprimer : '' ;
                $moyenne_classe = '';
                if( ($make_action=='consulter') && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) && ($eleve_id) )
                {
                  $note_moyenne = ($tab_saisie[0][$matiere_id][0]['note']!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? number_format($tab_saisie[0][$matiere_id][0]['note'],1,'.','') : round($tab_saisie[0][$matiere_id][0]['note']*5).'&nbsp;%' ) : '-' ;
                  $moyenne_classe = ' Moyenne de classe : '.$note_moyenne;
                }
                $html .= '<tr id="note_'.$matiere_id.'_0"><td class="now moyenne">'.$note.'</td><td class="now"><span class="notnow"'.$infobulle.'>'.html($appreciation).$action.'</span>'.$moyenne_classe.'</td></tr>'.NL;
              }
              // Bulletin - Appréciations intermédiaires (HTML)
              if( ($make_html) && ($make_officiel) && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR']) )
              {
                // $tab_saisie[$eleve_id][$matiere_id] n’est pas défini si bulletin sans note et pas d’appréciation encore saisie
                if(isset($tab_saisie[$eleve_id][$matiere_id]))
                {
                  foreach($tab_saisie[$eleve_id][$matiere_id] as $prof_id => $tab)
                  {
                    if($prof_id) // Sinon c’est la note.
                    {
                      extract($tab);  // $prof_info $appreciation $note
                      $actions = '';
                      if( ($make_action=='modifier') && ($prof_id==$_SESSION['USER_ID']) )
                      {
                        $actions .= ' <button type="button" class="modifier">Modifier</button> <button type="button" class="supprimer">Supprimer</button>';
                      }
                      elseif(in_array($BILAN_ETAT,array('2rubrique','3mixte','4synthese')))
                      {
                        if($prof_id!=$_SESSION['USER_ID']) { $actions .= ' <button type="button" class="signaler">Signaler une faute</button>'; }
                        if($droit_corriger_appreciation)   { $actions .= ' <button type="button" class="corriger">Corriger une faute</button>'; }
                      }
                      $html .= '<tr id="appr_'.$matiere_id.'_'.$prof_id.'"><td colspan="2" class="now"><div class="notnow">'.html($prof_info).$actions.'</div><div class="appreciation">'.html($appreciation).'</div></td></tr>'.NL;
                    }
                  }
                }
                if($make_action=='modifier')
                {
                  if(!isset($tab_saisie[$eleve_id][$matiere_id][$_SESSION['USER_ID']]))
                  {
                    $texte_classe = empty($is_appreciation_groupe) ? '' : ' sur la classe' ;
                    $html .= '<tr id="appr_'.$matiere_id.'_'.$_SESSION['USER_ID'].'"><td colspan="2" class="now"><div class="hc"><button type="button" class="ajouter">Ajouter une appréciation'.$texte_classe.'.</button></div></td></tr>'.NL;
                  }
                }
              }
              $html .= '</tbody></table>'.NL;
            }
            // Examen de présence des appréciations intermédiaires et des notes
            if( ($make_action=='examiner') && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) && !in_array($matiere_id,$tab_moyenne_exception_matieres) && ( !isset($tab_saisie[$eleve_id][$matiere_id][0]) || ($tab_saisie[$eleve_id][$matiere_id][0]['note']===NULL) ) )
            {
              $tab_resultat_examen[$matiere_nom][] = 'Absence de positionnement pour '.html($eleve_nom_prenom);
            }
            if( ($make_action=='examiner') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR']) && ( (!isset($tab_saisie[$eleve_id][$matiere_id])) || (max(array_keys($tab_saisie[$eleve_id][$matiere_id]))==0) ) )
            {
              $tab_resultat_examen[$matiere_nom][] = 'Absence d’appréciation pour '.html($eleve_nom_prenom);
            }
            // Impression des appréciations intermédiaires (PDF)
            $tab_saisie_rubrique = NULL;
            if( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_RUBRIQUE_LONGUEUR']) )
            {
              $nb_lignes_en_moins = ( $_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'] || $_SESSION['OFFICIEL']['BULLETIN_BARRE_ACQUISITIONS'] ) ? $nb_lignes_matiere_intitule_et_marge : $nb_lignes_matiere_marge ;
              $tab_saisie_rubrique = ( (!isset($tab_saisie[$eleve_id][$matiere_id])) || (max(array_keys($tab_saisie[$eleve_id][$matiere_id]))==0) ) ? NULL : $tab_saisie[$eleve_id][$matiere_id];
              $nb_lignes_hauteur = $tab_nb_lignes[$eleve_id][$matiere_id] - $nb_lignes_en_moins;
              if(is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]))
              {
                $pdf->appreciation_rubrique( $tab_saisie_rubrique , $nb_lignes_hauteur , $sans_cadre_appreciation );
                if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'appreciation_rubrique' , array( $tab_saisie_rubrique , $nb_lignes_hauteur , $sans_cadre_appreciation ) ); }
              }
            }
            if( ($make_action=='imprimer') && !is_null($tab_nb_blocs_tableau_croise_eleve[$eleve_id]) )
            {
              $tab_score = isset($tab_synthese_indicateur[$eleve_id][$matiere_id]) ? $tab_synthese_indicateur[$eleve_id][$matiere_id] : array() ;
              $pdf->ligne_tableau_matiere( $tab_croisement_synthese , $matiere_id , $matiere_nom , $tab_score , $tab_saisie_rubrique , $moyenne_eleve , $moyenne_classe );
              if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_tableau_matiere' , array( $tab_croisement_synthese , $matiere_id , $matiere_nom , $tab_score , $tab_saisie_rubrique , $moyenne_eleve , $moyenne_classe ) ); }
            }
          }
        }
        // Bulletin - Appréciation générale + Moyenne générale
        if( ($make_officiel) && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_GENERALE_LONGUEUR']) && ( ($make_action=='tamponner') || ($make_action=='consulter') ) )
        {
          if( ($make_html) || ($make_graph) )
          {
            $html .= '<table class="bilan" style="width:900px"><tbody>'.NL;
            $html .= '<tr><th colspan="2">Synthèse générale</th></tr>'.NL;

            // Bulletin - Info saisies périodes antérieures
            if(isset($tab_saisie_avant[$eleve_id][0]))
            {
              $tab_periode_liens  = array();
              $tab_periode_textes = array();
              foreach($tab_saisie_avant[$eleve_id][0] as $periode_id => $tab_prof)
              {
                $tab_ligne = array(0=>''); // Pour forcer la note à être le 1er indice ; sert aussi à indiquer la période.
                foreach($tab_prof as $prof_id => $tab)
                {
                  extract($tab);  // $prof_info $appreciation $note
                  if(!$prof_id) // C’est la note.
                  {
                    if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
                    {
                      $tab_ligne[0] = ($note!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $note : ($note*5).'&nbsp;%' ) : '-' ;
                    }
                  }
                  else
                  {
                    $tab_ligne[$prof_id] = html('['.$prof_info.'] '.$appreciation);
                  }
                }
                if(!empty($tab_decision_avant[$eleve_id][$periode_id]))
                {
                  if( $affichage_decision_mention && $tab_decision_avant[$eleve_id][$periode_id]['mention'][0] )
                  {
                    $tab_ligne[] = html($tab_decision_avant[$eleve_id][$periode_id]['mention'][1]);
                  }
                  if( $affichage_decision_engagement && $tab_decision_avant[$eleve_id][$periode_id]['engagement'][0] )
                  {
                    $tab_ligne[] = html($tab_decision_avant[$eleve_id][$periode_id]['engagement'][1]);
                  }
                  if( $affichage_decision_orientation && $tab_decision_avant[$eleve_id][$periode_id]['orientation'][0] )
                  {
                    $tab_ligne[] = html($tab_decision_avant[$eleve_id][$periode_id]['orientation'][1]);
                  }
                }
                $tab_ligne[0] = '<b>'.html($tab_periode_avant[$periode_id]).'&nbsp;:&nbsp;'.$tab_ligne[0].'</b>';
                $tab_periode_liens[]  = '<a href="#toggle" class="toggle_plus"'.infobulle('Voir / masquer les informations de cette période.').' id="to_'.$eleve_id.'_avant_'.'0'.'_'.$periode_id.'"></a> '.html($tab_periode_avant[$periode_id]);
                $tab_periode_textes[] = '<div id="'.$eleve_id.'_avant_'.'0'.'_'.$periode_id.'" class="appreciation bordertop hide">'.implode('<br>',$tab_ligne).'</div>';
              }
              $html .= '<tr><td colspan="2" class="avant">'.implode('&nbsp;&nbsp;&nbsp;',$tab_periode_liens).implode('',$tab_periode_textes).'</td></tr>'.NL;
            }

            if( ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_GENERALE']) && ( $_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'] || $eleve_id ) )
            {
              $note = ($moyenne_generale_eleve_enregistree!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $moyenne_generale_eleve_enregistree : round($moyenne_generale_eleve_enregistree*5).'&nbsp;%' ) : '-' ;
              $moyenne_classe = '';
              if( ($make_action=='consulter') && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE']) && ($eleve_id) )
              {
                $note_moyenne = ($moyenne_generale_classe_enregistree!==NULL) ? ( ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? $moyenne_generale_classe_enregistree : round($moyenne_generale_classe_enregistree*5).'&nbsp;%' ) : '-' ;
                $moyenne_classe = ' Moyenne de classe : '.$note_moyenne;
              }
              $html .= '<tr><td class="now moyenne">'.$note.'</td><td class="now" style="width:850px"><span class="notnow">Moyenne générale (calculée / actualisée automatiquement).</span>'.$moyenne_classe.'</td></tr>'.NL;
            }
            // Décisions du conseil
            $html_mention     = ($eleve_id && $affichage_decision_mention)     ? '<div class="decision" id="div_mention" data-value="'.$tab_decision[$eleve_id]['mention'][0].'">'.html($tab_decision[$eleve_id]['mention'][1]).'</div>' : '' ;
            $html_engagement  = ($eleve_id && $affichage_decision_engagement)  ? '<div class="decision" id="div_engagement" data-value="'.$tab_decision[$eleve_id]['engagement'][0].'">'.html($tab_decision[$eleve_id]['engagement'][1]).'</div>' : '' ;
            $html_orientation = ($eleve_id && $affichage_decision_orientation) ? '<div class="decision" id="div_orientation" data-value="'.$tab_decision[$eleve_id]['orientation'][0].'">'.html($tab_decision[$eleve_id]['orientation'][1]).'</div>' : '' ;
            if($is_appreciation_generale_enregistree)
            {
              extract($tab_appreciation_generale);  // $prof_info $appreciation $note
              $actions = '';
              if($make_action=='tamponner') // Pas de test ($prof_id_appreciation_generale==$_SESSION['USER_ID']) car l’appréciation générale est unique avec saisie partagée.
              {
                $actions .= ' <button type="button" class="modifier">Modifier</button> <button type="button" class="supprimer">Supprimer</button>';
              }
              elseif(in_array($BILAN_ETAT,array('2rubrique','3mixte','4synthese')))
              {
                if($prof_id_appreciation_generale!=$_SESSION['USER_ID']) { $actions .= ' <button type="button" class="signaler">Signaler une faute</button>'; }
                if($droit_corriger_appreciation)                         { $actions .= ' <button type="button" class="corriger">Corriger une faute</button>'; }
              }
              $html .= '<tr id="appr_0_'.$prof_id_appreciation_generale.'"><td colspan="2" class="now"><div class="notnow">'.html($prof_info).$actions.'</div><div class="appreciation">'.html($appreciation).'</div>'.$html_mention.$html_engagement.$html_orientation.'</td></tr>'.NL;
            }
            elseif($make_action=='tamponner')
            {
              $texte_classe = empty($is_appreciation_groupe) ? '' : ' sur la classe' ;
              $html .= '<tr id="appr_0_'.$_SESSION['USER_ID'].'"><td colspan="2" class="now">'.$html_mention.$html_engagement.$html_orientation.'<div class="hc"><button type="button" class="ajouter">Ajouter l’appréciation générale'.$texte_classe.'.</button></div></td></tr>'.NL;
            }
            elseif($html_mention || $html_engagement || $html_orientation)
            {
              $html .= '<tr><td colspan="2" class="now">'.$html_mention.$html_engagement.$html_orientation.'</td></tr>'.NL;
            }
            $html .= '</tbody></table>'.NL;
          }
        }
        // Examen de présence de l’appréciation générale
        if( ($make_action=='examiner') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_GENERALE_LONGUEUR']) && (in_array(0,$tab_rubrique_id)) && !$is_appreciation_generale_enregistree )
        {
          $tab_resultat_examen['Synthèse générale'][] = 'Absence d’appréciation générale pour '.html($eleve_nom_prenom);
        }
        // Impression de l’appréciation générale + Moyenne générale
        if( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['BULLETIN_APPRECIATION_GENERALE_LONGUEUR']) )
        {
          // Décisions du conseil
          if($eleve_id && $affichage_decision_mention && $tab_decision[$eleve_id]['mention'][0])
          {
            $tab_appreciation_generale['mention'] = $tab_decision[$eleve_id]['mention'][1];
          }
          if($eleve_id && $affichage_decision_engagement && $tab_decision[$eleve_id]['engagement'][0])
          {
            $tab_appreciation_generale['engagement'] = $tab_decision[$eleve_id]['engagement'][1];
          }
          if($eleve_id && $affichage_decision_orientation && $tab_decision[$eleve_id]['orientation'][0])
          {
            $tab_appreciation_generale['orientation'] = $tab_decision[$eleve_id]['orientation'][1];
          }
          if($is_appreciation_generale_enregistree)
          {
            if( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='sans') || ( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='tampon') && (!$tab_signature[0]) ) || ( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='signature') && (!$tab_signature[$prof_id_appreciation_generale]) ) || ( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='signature_ou_tampon') && (!$tab_signature[0]) && (!$tab_signature[$prof_id_appreciation_generale]) ) )
            {
              $tab_image_tampon_signature = NULL;
            }
            else
            {
              $tab_image_tampon_signature = ( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='signature') || ( ($_SESSION['OFFICIEL']['TAMPON_SIGNATURE']=='signature_ou_tampon') && $tab_signature[$prof_id_appreciation_generale]) ) ? $tab_signature[$prof_id_appreciation_generale] : $tab_signature[0] ;
            }
          }
          else
          {
            $tab_image_tampon_signature = in_array($_SESSION['OFFICIEL']['TAMPON_SIGNATURE'],array('tampon','signature_ou_tampon')) ? $tab_signature[0] : NULL;
          }
          $moyenne_generale_eleve_affichee  = NULL;
          $moyenne_generale_classe_affichee = NULL;
          if( ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES']) && ($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_GENERALE']) )
          {
            $moyenne_generale_eleve_affichee = $moyenne_generale_eleve_enregistree;
            if($_SESSION['OFFICIEL']['BULLETIN_MOYENNE_CLASSE'])
            {
              $moyenne_generale_classe_affichee = $moyenne_generale_classe_enregistree;
            }
          }
          $nb_lignes_assiduite_et_pp_et_message_et_legende = $nb_lignes_assiduite+$nb_lignes_prof_principal+$nb_lignes_supplementaires+$nb_lignes_legendes;
          $pdf->appreciation_generale( $prof_id_appreciation_generale , $tab_appreciation_generale , $tab_image_tampon_signature , $nb_lignes_appreciation_generale_avec_intitule , $nb_lignes_assiduite_et_pp_et_message_et_legende , $moyenne_generale_eleve_affichee , $moyenne_generale_classe_affichee );
          if($is_archive)
          {
            if(!empty($tab_image_tampon_signature))
            {
              // On remplace l’image par son md5
              $image_contenu = $tab_image_tampon_signature['contenu'];
              $image_md5     = md5($image_contenu);
              $tab_archive['image'][$image_md5] = $image_contenu;
              $tab_archive['user'][$eleve_id]['image_md5'][] = $image_md5;
              $tab_image_tampon_signature['contenu'] = $image_md5;
            }
            $tab_archive['user'][$eleve_id][] = array( 'appreciation_generale' , array( $prof_id_appreciation_generale , $tab_appreciation_generale , $tab_image_tampon_signature , $nb_lignes_appreciation_generale_avec_intitule , $nb_lignes_assiduite_et_pp_et_message_et_legende , $moyenne_generale_eleve_affichee , $moyenne_generale_classe_affichee ) );
          }
        }
        $tab_pdf_lignes_additionnelles = array();
        // Bulletin - Absences et retard
        if( ($make_officiel) && ($affichage_assiduite) && empty($is_appreciation_groupe) )
        {
          $texte_assiduite = texte_ligne_assiduite($tab_assiduite[$eleve_id]);
          if( ($make_html) || ($make_graph) )
          {
            $html .= '<div class="i">'.$texte_assiduite.'</div>'.NL;
          }
          elseif($make_action=='imprimer')
          {
            $tab_pdf_lignes_additionnelles[] = $texte_assiduite;
          }
        }
        // Bulletin - Professeurs principaux
        if( ($make_officiel) && ($affichage_prof_principal) )
        {
          if( ($make_html) || ($make_graph) )
          {
            $html .= '<div class="i">'.$texte_prof_principal.'</div>'.NL;
          }
          elseif($make_action=='imprimer')
          {
            $tab_pdf_lignes_additionnelles[] = $texte_prof_principal;
          }
        }
        // Bulletin - Ligne additionnelle
        if( ($make_action=='imprimer') && ($nb_lignes_supplementaires) )
        {
          $tab_pdf_lignes_additionnelles[] = $_SESSION['OFFICIEL']['BULLETIN_LIGNE_SUPPLEMENTAIRE'];
        }
        if(count($tab_pdf_lignes_additionnelles))
        {
          $pdf->afficher_lignes_additionnelles($tab_pdf_lignes_additionnelles);
          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'afficher_lignes_additionnelles' , array( $tab_pdf_lignes_additionnelles ) ); }
        }
        // Bulletin - Date de naissance
        if( ($make_officiel) && ($date_naissance) && ( ($make_html) || ($make_graph) ) )
        {
          $html .= '<div class="i">'.To::texte_ligne_naissance($date_naissance).'</div>'.NL;
        }
        // Bulletin - Légende
        if( ( ($make_html) || ($make_pdf) ) && ($legende=='oui') && empty($is_appreciation_groupe) )
        {
          if($make_html) { $html .= $legende_html; }
          if($make_pdf)  { $pdf->legende($aff_prop_sans_score); }
          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'legende' , array() ); }
        }
        // Page supplémentaire avec les appréciations sur le groupe classe
        if(!empty($ajout_page_bilan_classe))
        {
          $pdf->ajouter_page_bilan_classe( $BILAN_TYPE , $tab_bilan_classe );
          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ajouter_page_bilan_classe' , array( $BILAN_TYPE , $tab_bilan_classe ) ); }
        }
        elseif(!isset($ajout_page_bilan_classe))
        {
          $ajout_page_bilan_classe = 0;
        }
        // Indiquer a posteriori le nombre de pages par élève
        if($make_pdf)
        {
          $page_nb = $pdf->reporter_page_nb($ajout_page_bilan_classe);
          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'reporter_page_nb' , array( $ajout_page_bilan_classe ) ); }
          if( !empty($page_parite) && ($page_nb%2) )
          {
            $pdf->ajouter_page_blanche();
          }
        }
        // Mémorisation des pages de début et de fin pour chaque élève pour découpe et archivage ultérieur
        if($make_action=='imprimer')
        {
          $page_debut  = (isset($page_fin)) ? $page_fin+1 : 1 ;
          $page_fin    = $pdf->page;
          $page_nombre = $page_fin - $page_debut + 1;
          $tab_pages_decoupe_pdf[$eleve_id][$numero_tirage] = array( $eleve_nom_prenom , $page_debut.'-'.$page_fin , $page_nombre );
        }
      }
    }
  }

  if( !$make_officiel && $make_html && ($_SESSION['USER_PROFIL_TYPE']=='professeur') )
  {
    $script = 'var CSRF = "'.$CSRF_eval_eclair.'";'; // Pour les évaluations à la volée.
    $html .= '<script>'.$script.'</script>'.NL;
  }

  // ajout du tableau à double entrée si besoin
  if(!empty($html_tableau_croise))
  {
    $html_tableau_croise .= '</tbody></table>'.NL;
    $html = str_replace( $emplacement_tableau_croise , $html_tableau_croise , $html );
  }

  // ////////////////////////////////////////////////////////////////////////////////////////////////////
  // On enregistre les sorties HTML et PDF
  // ////////////////////////////////////////////////////////////////////////////////////////////////////

  if($make_html) { FileSystem::ecrire_fichier(   CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','individuel',$fichier_nom).'.html' , $html ); }
  if($make_pdf)  { FileSystem::ecrire_objet_pdf( CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','individuel',$fichier_nom).'.pdf'  , $pdf  ); }

  // ////////////////////////////////////////////////////////////////////////////////////////////////////
  // On fabrique les options js pour le diagramme graphique
  // ////////////////////////////////////////////////////////////////////////////////////////////////////

  if( $make_graph && (count($tab_graph_data)) )
  {
    $objet = ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? 'Moyenne' : 'Pourcentage' ;
    // Matières sur l’axe des abscisses
    Json::add_row( 'script' , 'ChartOptions.title.text = null;' );
    Json::add_row( 'script' , 'ChartOptions.xAxis.categories = ['.implode(',',$tab_graph_data['categories']).'];' );
    // Second axe des ordonnés pour les moyennes
    if(!$_SESSION['OFFICIEL']['BULLETIN_MOYENNE_SCORES'])
    {
      Json::add_row( 'script' , 'delete ChartOptions.yAxis[1];' );
    }
    else
    {
      $ymax         = ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ? 20 : 100 ;
      $tickInterval = ($_SESSION['OFFICIEL']['BULLETIN_CONVERSION_SUR_20']) ?  5 :  25 ;
      Json::add_row( 'script' , 'ChartOptions.yAxis[1] = { min: 0, max: '.$ymax.', tickInterval: '.$tickInterval.', gridLineColor: "#C0D0E0", title: { style: { color: "#333" } , text: "'.$objet.'s" }, opposite: true };' );
    }
    // Séries de valeurs ; périodes antérieures éventuelles en dessous de la classe en dessous de l’élève
    $tab_graph_series = array();
    $tab_color = array('#d0c','#d60'); // du rose et du beige, pour éviter rouge / orange / jaune / vert souvent déjà usitées pour les états d’acquisition (et bleu déjà pris pour la période courante)
    $icolor = 0;
    if($eleve_id)
    {
      foreach( $_SESSION['ACQUIS'] as $acquis_id => $tab_acquis_info )
      {
          $tab_graph_series['A'.$acquis_id] = '{ name: "'.addcslashes($tab_acquis_info['LEGENDE'],'"').'", data: ['.implode(',',$tab_graph_data['series_data_'.$acquis_id]).'] }';
      }
      if($aff_prop_sans_score)
      {
        $tab_graph_series['A0'] = '{ name: "'.addcslashes($_SESSION['ETAT_ACQUISITION_NEUTRE_LEGENDE'],'"').'", data: ['.implode(',',$tab_graph_data['series_data_0']).'] }';
      }
    }
    foreach($tab_periode_avant as $periode_id => $periode_nom)
    {
      if(isset($tab_graph_data['series_data_periode'.$periode_id]))
      {
        $tab_graph_series['periode'.$periode_id]  = '{ type: "line", name: "'.addcslashes($periode_nom,'"').'", data: ['.implode(',',$tab_graph_data['series_data_periode'.$periode_id]).'], marker: {symbol: "circle"}, yAxis: 1, color: "'.$tab_color[$icolor%2].'", visible: false }';
        $icolor++;
      }
    }
    if(isset($tab_graph_data['series_data_MoyClasse']))
    {
      $tab_graph_series['MoyClasse'] = '{ type: "line", name: "'.$objet.' classe", data: ['.implode(',',$tab_graph_data['series_data_MoyClasse']).'], marker: {symbol: "circle"}, yAxis: 1, color: "#999" }';
    }
    if(isset($tab_graph_data['series_data_MoyEleve']))
    {
      $tab_graph_series['MoyEleve']  = '{ type: "line", name: "'.$objet.' élève", data: ['.implode(',',$tab_graph_data['series_data_MoyEleve']).'], marker: {symbol: "circle"}, yAxis: 1, color: "#00F", lineWidth: 3 }';
    }
    Json::add_row( 'script' , 'ChartOptions.series = ['.implode(',',$tab_graph_series).'];' );
  }
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Elaboration de la synthèse collective en HTML / PDF / CSV
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($type_synthese)
{
  // start HTML
  $html  = $affichage_direct ? '' : '<style>'.$_SESSION['CSS'].'</style>'.NL;
  $html .= $affichage_direct ? '' : '<h1>Synthèse '.$tab_titre[$synthese_modele].'</h1>'.NL;
  $html .= '<h2>'.html($texte_periode).'<br>'.$texte_precision_html.'</h2>'.NL;
  // start CSV
  $csv = new CSV();
  $csv->add( 'Synthèse '.$tab_titre[$synthese_modele] , 1 )->add( 'Exploitation tableur' , 1 )->add( $texte_periode , 1 )->add( $texte_synthese_indicateur_pdf_csv , 2 );
  // Appel de la classe et redéfinition de qqs variables supplémentaires pour la mise en page PDF
  // On définit l’orientation la plus adaptée
  $orientation_auto = ($matiere_nb+$rubrique_nb>$eleve_nb) ? 'portrait' : 'landscape' ;
  $pdf = new PDF_synthese_tableau( $make_officiel , 'A4' /*page_size*/ , $orientation_auto , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond , $legende );
  $pdf->initialiser( $eleve_nb , $matiere_nb , $rubrique_nb );
  $pdf->entete( 'Synthèse '.$tab_titre[$synthese_modele] , $texte_synthese_indicateur_pdf_csv , $texte_periode.' ('.$texte_precision_pdf_csv.')' );
  // 1ère ligne
  $pdf->ligne_tete_cellule_debut( $groupe_nom );
  $html_table_head = '<thead><tr><th class="nu">'.html($groupe_nom).'</th>';
  $csv->add( $groupe_nom );
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
  {
    extract($tab_eleve);  // $eleve_nom $eleve_prenom $date_naissance $eleve_id_gepi
    $eleve_nom_prenom = To::texte_eleve_identite($eleve_nom,$eleve_prenom,$eleves_ordre);
    $pdf->ligne_tete_cellule_corps( $eleve_nom_prenom );
    $html_table_head .= '<th class="header"><dfn>'.html($eleve_nom_prenom).'</dfn></th>';
    $csv->add( $eleve_nom_prenom );
  }
  $pdf->ligne_tete_fin();
  $html_table_head .= '</tr></thead>'.NL;
  $csv->add( NULL , 1 );
  // lignes suivantes
  $html_table_body = '';
  foreach($tab_matiere as $matiere_id => $tab)  // Pour chaque matière...
  {
    $matiere_nom = $tab['matiere_nom'];
    $lignes_nb = count($tab_rubriques[$matiere_id]) + 1.5;
    $pdf->ligne_corps_cellule_debut_matiere( $matiere_nom , $lignes_nb );
    $html_table_body .= '<tbody>'.NL;
    $html_table_body .= '<tr class="vide"><th class="nu"></th><td class="nu" colspan="'.$eleve_nb.'"></td></tr>';
    $html_table_body .= '<tr><th>'.html($matiere_nom).'</th>';
    $csv->add( NULL , 1 )->add( $matiere_nom );
    foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
    {
      $score = isset($tab_synthese_indicateur[$eleve_id][$matiere_id]['total']) ? $tab_synthese_indicateur[$eleve_id][$matiere_id]['total'] : FALSE ;
      $pdf->afficher_score_bilan( $score , 0 /*br*/, TRUE /*bold*/ );
      $html_table_body .= Html::td_score($score,'score','%','',TRUE);
      $csv->add( $score );
    }
    $pdf->ligne_corps_fin_matiere();
    $html_table_body .= '</tr>';
    $html_table_body .= '<tr class="vide"><td></td><td colspan="'.$eleve_nb.'"></td></tr>';
    $csv->add( NULL , 2 );
    foreach($tab_rubriques[$matiere_id] as $synthese_ref => $synthese_nom)
    {
      $pdf->ligne_corps_cellule_debut_rubrique($synthese_nom);
      $html_table_body .= '<tr><td>'.html($synthese_nom).'</td>';
      $csv->add( $synthese_nom );
      foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
      {
        $score = isset($tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref]) ? $tab_synthese_indicateur[$eleve_id][$matiere_id][$synthese_ref] : FALSE ;
        $pdf->afficher_score_bilan( $score , 0 /*br*/ );
        $html_table_body .= Html::td_score($score,'score','%','',FALSE);
        $csv->add( $score );
      }
      $pdf->ligne_corps_fin_rubrique();
      $html_table_body .= '</tr>';
      $csv->add( NULL , 1 );
    }
    $html_table_body .= '</tbody>'.NL;
  }
  $csv->add( NULL , 1 );
  // sortie HTML
  $html .= '<hr>'.NL.'<h2>Tableau de synthèse - '.$texte_synthese_indicateur_html.'</h2>'.NL;
  $html .= '<table id="table_s" class="bilan_synthese">'.NL.$html_table_head.$html_table_body.'</table>'.NL;
  // Légende
  if( ( ($make_html) || ($make_pdf) ) && ($legende=='oui') )
  {
    if($make_pdf)  { $pdf->legende(); }
    if($make_html) { $html .= Html::legende( array('score_bilan'=>TRUE) ); }
  }
  $html .= '<style>th.header{text-align:center;vertical-align:bottom} tr.vide{font-size:40%}</style>'.NL;
  // On enregistre les sorties HTML et PDF et CSV
  FileSystem::ecrire_fichier(   CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','synthese',$fichier_nom).'.html' , $html );
  FileSystem::ecrire_objet_pdf( CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','synthese',$fichier_nom).'.pdf'  , $pdf );
  FileSystem::ecrire_objet_csv( CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','synthese',$fichier_nom).'.csv'  , $csv );
}

?>