<?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_items.ajax.php]
 * [./_inc/code_officiel_***.php]
 */

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

/*
$type_individuel | $type_synthese | $type_bulletin
$releve_modele [ matiere | matieres | multimatiere | selection | evaluation | professeur | tableau_eval ]
*/

$matiere_et_groupe = ($releve_modele=='matiere') ? $matiere_nom.' - '.$groupe_nom : $groupe_nom ;

// Chemins d’enregistrement

$fichier_nom = ($make_action!='imprimer') ? 'releve_item_'.$releve_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() ;

// Si pas grille générique et si notes demandées ou besoin pour colonne bilan ou besoin pour synthèse
$calcul_acquisitions = ( $type_synthese || $type_bulletin || $aff_etat_acquisition ) ? TRUE : FALSE ;

// Initialisation de tableaux

$tab_item_infos       = array();  // [item_id] => array(item_ref,item_nom,item_coef,item_cart,item_s2016,item_lien,calcul_methode,calcul_limite,calcul_retroactif);
$tab_matiere_item     = array();  // [matiere_id][item_id] => item_nom
$tab_eleve_infos      = array();  // [eleve_id] => array(eleve_INE,eleve_nom,eleve_prenom,date_naissance,eleve_id_gepi)
$tab_matiere          = array();  // [matiere_id] => array(matiere_nom,matiere_nb_demandes)
$tab_eval             = array();  // [eleve_id][matiere_id|devoir_id][item_id][devoir]
$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],
);

// Initialisation de variables

$precision_socle       = $only_socle ? ', '.$tab_remove_strong[0].'restreint au socle'.$tab_remove_strong[1] : '' ;
$precision_valeur      = $only_valeur ? ', '.$tab_remove_strong[0].'sans codes neutres'.$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 aux notes de '.$prof_texte_only.$tab_remove_strong[1] : '' ;

// Initialement de 15, mais certains en veulent toujours plus !
// (ne pas mettre moins de 15 car le formulaire permet de choisir entre 1 à 15 ou automatique selon le nombre de notes)
define('NB_CASES_MAX',50);

if( ($make_html) || ($make_pdf) )
{
  // pour avoir des variables définies, seul [releve_items_professeur] utilisant ceci
  $professeur = ($prof_objet_id) ? $prof_texte_objet : '' ;
  $evaluation = empty($evaluation_nom) ? 'd’évaluations sélectionnées' : 'de l’évaluation '.$evaluation_nom ;
  $tab_titre_etat = array(
  'tous'              => ($releve_modele!='professeur') ? 'évalués' : '' ,
  'acquis'            => $tab_remove_strong[0].'réussis'.$tab_remove_strong[1] ,
  'acquis_moyens'     => $tab_remove_strong[0].'réussis ou médians'.$tab_remove_strong[1] ,
  'non_acquis_moyens' => $tab_remove_strong[0].'échoués ou médians'.$tab_remove_strong[1] ,
  'non_acquis'        => $tab_remove_strong[0].'échoués'.$tab_remove_strong[1] ,
  'en_baisse'         => $tab_remove_strong[0].'en baisse'.$tab_remove_strong[1] ,
  );
  $tab_titre_modele = array(
    'matiere'      => '- '.$matiere_nom ,
    'matieres'     => 'de matières sélectionnées' ,
    'multimatiere' => 'pluridisciplinaire' ,
    'selection'    => 'sélectionnés' ,
    'evaluation'   => $evaluation ,
    'tableau_eval' => $evaluation ,
    'professeur'   => 'd’évaluations de '.$professeur ,
  );
  $bilan_intro = ($releve_modele!='tableau_eval') ? 'Bilan ' : 'Tableau ' ;
  $bilan_titre_html = 'd’items '.$tab_titre_etat[$only_etat].' '.html($tab_titre_modele[$releve_modele]);
  $bilan_titre_pdf_csv_json = str_replace($tab_remove_strong,'',$bilan_titre_html);
  $info_ponderation_complete = ($with_coef) ? '(pondérée)' : '(non pondérée)' ;
  $info_ponderation_courte   = ($with_coef) ? 'pondérée'   : 'simple' ;
  if(!$aff_coef)  { $texte_coef  = ''; }
  if(!$aff_socle) { $texte_socle = ''; }
  if(!$aff_socle) { $texte_s2016 = ''; }
  if(!$aff_comm)  { $texte_comm  = ''; }
  if(!$aff_lien)  { $texte_lien_avant = ''; }
  if(!$aff_lien)  { $texte_lien_apres = ''; }
  if(!$highlight_id) { $texte_fluo_avant = ''; }
  if(!$highlight_id) { $texte_fluo_apres = ''; }
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// 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_html = ( ($releve_modele!='evaluation') && ($releve_modele!='tableau_eval') )
                    ? 'Du '.$date_debut.' au '.$date_fin.' ('.$tab_precision_retroactif[$retroactif].$precision_socle.$precision_diagnostic.$precision_valeur.$precision_prof.').'
                    : 'Du '.$date_debut.' au '.$date_fin.' (sans notes antérieures'.$precision_socle.$precision_valeur.$precision_prof.').';
$texte_periode_pdf_csv = str_replace($tab_remove_strong,'',$texte_periode_html);

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Récupération de la liste des items travaillés durant la période choisie, pour les élèves selectionnés, pour la ou les matières ou les items indiqués ou le prof indiqué
// Récupération de la liste des matières travaillées
// ////////////////////////////////////////////////////////////////////////////////////////////////////

// $releve_modele [ matiere | matieres | multimatiere | selection | evaluation | professeur | tableau_eval ]

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

if(empty($is_appreciation_groupe))
{
  if($releve_modele=='matiere')
  {
    $tab_item_infos = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_bilan( $liste_eleve , $matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $date_sql_debut , $date_sql_fin , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ ) ;
      $tab_matiere[$matiere_id] = array(
        'matiere_nom'         => $matiere_nom,
        'matiere_nb_demandes' => DB_STRUCTURE_DEMANDE::DB_recuperer_demandes_autorisees_matiere($matiere_id),
      );
  }
  elseif($releve_modele=='multimatiere')
  {
    $matiere_id = -1;
    list($tab_item_infos,$tab_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_bilan( $liste_eleve , $matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $date_sql_debut , $date_sql_fin , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ );
  }
  elseif($releve_modele=='matieres')
  {
    $matiere_id = -1;
    list($tab_item_infos,$tab_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_bilan( $liste_eleve , $liste_matiere_id , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $date_sql_debut , $date_sql_fin , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ );
  }
  elseif($releve_modele=='tableau_eval')
  {
    $liste_evals = implode(',',$tab_evals);
    list($tab_item_infos,$tab_devoir,$tab_devoir_item) = DB_STRUCTURE_BILAN::DB_recuperer_items_devoirs( $liste_evals , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale );
  }
  else
  {
    if($releve_modele=='selection')
    {
      $liste_items = implode(',',$tab_items);
      list($tab_item_infos,$tab_matiere,$tab_item_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_selection( $liste_eleve , $liste_items , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $date_sql_debut , $date_sql_fin , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ );
    }
    elseif($releve_modele=='evaluation')
    {
      $liste_evals = implode(',',$tab_evals);
      list($tab_item_infos,$tab_matiere,$tab_item_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_devoirs( $liste_eleve , $liste_evals , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ );
    }
    elseif($releve_modele=='professeur')
    {
      list($tab_item_infos,$tab_matiere,$tab_item_matiere) = DB_STRUCTURE_BILAN::DB_recuperer_arborescence_professeur( $liste_eleve , $prof_objet_id , $only_socle , $only_diagnostic , $only_prof_id , $without_matiere_experimentale , $date_sql_debut , $date_sql_fin , $aff_domaine , $aff_theme , $aff_socle , $type_synthese /*with_abrev*/ );
    }
    // Si les items sont issus de plusieurs matières, alors on les regroupe en une seule.
    if(count($tab_matiere)>1)
    {
      $matiere_id = 0;
      $tab_matiere = array(
        0 => array(
          'matiere_nom'         => implode(' - ',$tab_matiere),
          'matiere_nb_demandes' => NULL,
        )
      );
    }
    else
    {
      $matiere_id  =     key($tab_matiere);
      $matiere_nom = current($tab_matiere);
      $tab_matiere = array(
        $matiere_id => array(
          'matiere_nom'         => $matiere_nom,
          'matiere_nb_demandes' => NULL,
         )
      );
      unset($tab_item_matiere);
    }
  }
}
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 , FALSE /*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 && !$make_brevet ) // Dans le cas d’un bilan officiel, ou d’une récupération pour une fiche brevet, où l’on regarde les élèves d’un groupe un à un, ce ne doit pas être bloquant.
{
  $indication_periode = ($releve_modele!='evaluation') ? ' sur la période '.$date_debut.' ~ '.$date_fin : '' ;
  Json::end( FALSE , 'Aucun item évalué'.$indication_periode.$precision_socle.$precision_diagnostic.$precision_valeur.$precision_prof.'.' );
}
$liste_item = implode( ',' , array_keys($tab_item_infos) );

// Liaisons au socle
if( $aff_socle && $type_individuel )
{
  $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
$longueur_ref_max = 0;
foreach($tab_item_infos as $item_id => $tab)
{
  $item_ref = ($tab[0]['ref_perso']) ? $tab[0]['ref_perso'] : $tab[0]['ref_auto'] ;
  $longueur_ref_max = max( $longueur_ref_max , strlen($item_ref) );
  $tab_item_infos[$item_id][0]['item_ref'] = $tab[0]['matiere_ref'].'.'.$item_ref;
  unset( $tab_item_infos[$item_id][0]['matiere_ref'] , $tab_item_infos[$item_id][0]['ref_perso'] , $tab_item_infos[$item_id][0]['ref_auto'] );
  if( $type_synthese || $type_tableau_eval )
  {
    $tab_item_infos[$item_id][0]['item_abrev'] = ($tab[0]['item_abrev']) ? $tab[0]['matiere_ref'].'.'.$tab[0]['item_abrev'] : $tab[0]['matiere_ref'].'.'.$item_ref ;
  }
}
$longueur_ref_max = $aff_reference ? $longueur_ref_max : 0 ;

// A ce stade : $matiere_id est un entier positif ou -1 si multimatières ou 0 si sélection d’items issus de plusieurs matières

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// 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'],
    'date_naissance' => $_SESSION['USER_NAISSANCE_DATE'],
    'eleve_id_gepi'  => $_SESSION['USER_ID_GEPI'],
    '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'   => '',
    'date_naissance' => NULL,
    'eleve_id_gepi'  => 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, 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).
{
  $annee_decalage = empty($_SESSION['NB_DEVOIRS_ANTERIEURS']) ? 0 : -1 ;
  $date_sql_debut_annee_scolaire = To::jour_debut_annee_scolaire('sql',$annee_decalage);
  if( ($releve_modele!='evaluation') && ($releve_modele!='tableau_eval') )
  {
    $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 ;
    }
    $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 , $only_valeur , FALSE /*onlynote*/ );
  }
  else
  {
    $DB_TAB = DB_STRUCTURE_BILAN::DB_lister_result_eleves_evals( $liste_eleve , $liste_item , $liste_evals , $matiere_id , $only_diagnostic , $only_prof_id , $only_valeur );
  }
  foreach($DB_TAB as $DB_ROW)
  {
    if($releve_modele=='tableau_eval')
    {
      $tab_eval[$DB_ROW['eleve_id']][$DB_ROW['devoir_id']][$DB_ROW['item_id']] = array(
        'note' => $DB_ROW['note'],
        'date' => $DB_ROW['date'],
        'info' => $DB_ROW['info'],
      );
    }
    else if( ($releve_modele=='evaluation') || ($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['matiere_id']][$DB_ROW['item_id']][] = array(
          'note' => $DB_ROW['note'],
          'date' => $DB_ROW['date'],
          'info' => $DB_ROW['info'],
        );
        $tab_matiere_item[$DB_ROW['matiere_id']][$DB_ROW['item_id']] = $tab_item_infos[$DB_ROW['item_id']][0]['item_nom'];
      }
    }
  }
}
if( !count($tab_eval) && !$make_officiel && !$make_brevet && ($releve_modele!='tableau_eval') ) // Dans le cas d’un bilan officiel, ou d’une récupération pour une fiche brevet, où l’on regarde les élèves d’un groupe un à un, ce ne doit pas être bloquant.
{
  $indication_periode = ($releve_modele!='evaluation') ? ' sur la période '.$date_debut.' ~ '.$date_fin : '' ;
  Json::end( FALSE , 'Aucune évaluation trouvée'.$indication_periode.$precision_socle.$precision_diagnostic.$precision_valeur.$precision_prof.'.' );
}
$matiere_nb = count( $tab_matiere_item , COUNT_NORMAL ); // 1 si $matiere_id >= 0 précédemment, davantage uniquement si $matiere_id = -1

// Cas d’un relevé par item où on veut aussi voir les élèves dans note
if( $type_individuel && ($releve_individuel_format=='item') && $eleves_sans_note )
{
  foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
  {
    foreach($tab_item as $item_id=>$item_nom)
    {
      foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
      {
        if(!isset($tab_eval[$eleve_id][$matiere_id][$item_id]))
        {
          $tab_eval[$eleve_id][$matiere_id][$item_id] = array();
        }
      }
    }
  }
}

// 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 / item
$tab_score_item_eleve         = array();  // Retenir les scores / item / élève
$tab_moyenne_scores_eleve     = array();  // Retenir la moyenne des scores d’acquisitions / matière / élève
$tab_moyenne_scores_item      = array();  // Retenir la moyenne des scores d’acquisitions / item
$tab_pourcentage_acquis_eleve = array();  // Retenir le pourcentage d’items acquis / matière / élève
$tab_pourcentage_acquis_item  = array();  // Retenir le pourcentage d’items acquis / item
$tab_infos_acquis_eleve       = array();  // Retenir les infos (nb acquis) à l’origine du tableau $tab_pourcentage_acquis_eleve / matière / élève
$tab_infos_acquis_item        = array();  // Retenir les infos (nb acquis) à l’origine du tableau $tab_pourcentage_acquis_item / item
$moyenne_moyenne_scores       = 0;  // moyenne des moyennes des scores d’acquisitions
$moyenne_pourcentage_acquis   = 0;  // moyenne des moyennes des pourcentages d’items acquis

/*
  On renseigne :
  $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id]
  $tab_score_item_eleve[$item_id][$eleve_id]
  $tab_moyenne_scores_eleve[$matiere_id][$eleve_id]
  $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id]
  $tab_infos_acquis_eleve[$matiere_id][$eleve_id]
*/

// Pour la synthèse d’items de plusieurs matières (/ élève)
$tab_total = array();

if(empty($is_appreciation_groupe))
{
  if($calcul_acquisitions)
  {
    $date_sql_debut = ($releve_modele!='evaluation') ? $date_sql_debut : NULL ; // Pour vérifier qu’il y a au moins une vraie note sur cette période
    // Pour chaque élève...
    foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
    {
      if( ($matiere_nb>1) && $type_synthese )
      {
        $tab_total[$eleve_id] = array
        (
          'somme_scores_coefs'   => 0 ,
          'somme_scores_simples' => 0 ,
          'nb_coefs'             => 0 ,
          'nb_scores'            => 0 ,
        ) + array_fill_keys( array_keys($_SESSION['ACQUIS']) , 0 );
      }
      // Si cet élève a été évalué...
      if(isset($tab_eval[$eleve_id]))
      {
        // Pour chaque matiere...
        foreach($tab_matiere as $matiere_id => $tab)
        {
          // Si cet élève a été évalué dans cette matière...
          if(isset($tab_eval[$eleve_id][$matiere_id]))
          {
            // Pour chaque item...
            foreach($tab_eval[$eleve_id][$matiere_id] as $item_id => $tab_devoirs)
            {
              extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_comm $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
              // calcul du bilan de l’item
              $score = OutilBilan::calculer_score( $tab_devoirs , $calcul_methode , $calcul_limite , $date_sql_debut );
              if( ($only_etat=='tous') || ( ($only_etat=='en_baisse') && OutilBilan::tester_en_baisse($tab_devoirs) ) || ( ($only_etat!='en_baisse') && OutilBilan::tester_acquisition( $score , $only_etat ) ) )
              {
                $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id] = $score;
                $tab_score_item_eleve[$item_id][$eleve_id] = $score;
              }
              else
              {
                unset( $tab_eval[$eleve_id][$matiere_id][$item_id] );
              }
            }
            if( ($only_etat=='tous') || !empty($tab_score_eleve_item[$eleve_id][$matiere_id]) )
            {
              // calcul des bilans des scores
              $tableau_score_filtre = array_filter($tab_score_eleve_item[$eleve_id][$matiere_id],'non_vide');
              $nb_scores = count( $tableau_score_filtre );
              // 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);
                if( ($matiere_nb>1) && $type_synthese )
                {
                  // Total multimatières avec ou sans coef
                  $tab_total[$eleve_id]['somme_scores_coefs']   += $somme_scores_ponderes;
                  $tab_total[$eleve_id]['somme_scores_simples'] += $somme_scores_simples;
                  $tab_total[$eleve_id]['nb_coefs']             += $somme_coefs;
                  $tab_total[$eleve_id]['nb_scores']            += $nb_scores;
                }
              }
              // ... un pour la moyenne des pourcentages d’acquisition
              if($with_coef) { $tab_moyenne_scores_eleve[$matiere_id][$eleve_id] = ($somme_coefs) ? round($somme_scores_ponderes/$somme_coefs,0) : FALSE ; }
              else           { $tab_moyenne_scores_eleve[$matiere_id][$eleve_id] = ($nb_scores)   ? round($somme_scores_simples/$nb_scores,0)    : FALSE ; }
              // ... un pour le nombre d’items considérés acquis ou pas
              if($nb_scores)
              {
                $tab_acquisitions = OutilBilan::compter_nombre_acquisitions_par_etat( $tableau_score_filtre , 0 /*aff_prop_sans_score*/ );
                $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] = OutilBilan::calculer_pourcentage_acquisition_items( $tab_acquisitions , $nb_scores );
                $tab_infos_acquis_eleve[$matiere_id][$eleve_id]       = OutilBilan::afficher_nombre_acquisitions_par_etat( $tab_acquisitions , FALSE /*detail_couleur*/ );
                if( ($matiere_nb>1) && $type_synthese )
                {
                  // Total multimatières
                  foreach( $tab_acquisitions as $acquis_id => $acquis_nb )
                  {
                    $tab_total[$eleve_id][$acquis_id] += $acquis_nb;
                  }
                }
              }
              else
              {
                $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] = FALSE;
                $tab_infos_acquis_eleve[$matiere_id][$eleve_id]       = FALSE;
              }
            }
            else
            {
              // Cas où, à cause de la restriction à des items échoués ou réussis, on n’a plus d’évaluation pour un élève dans une matière
              unset( $tab_eval[$eleve_id][$matiere_id] );
            }
          }
        }
        if( ($only_etat!='tous') && empty($tab_eval[$eleve_id]) )
        {
        // Cas où, à cause de la restriction à des items échoués ou réussis, on n’a plus d’évaluation pour un élève
          unset( $tab_eval[$eleve_id] );
        }
        if( ($matiere_nb>1) && $type_synthese )
        {
          // On prend la matière 0 pour mettre les résultats toutes matières confondues
          if($with_coef) { $tab_moyenne_scores_eleve[0][$eleve_id] = ($tab_total[$eleve_id]['nb_coefs'])  ? round($tab_total[$eleve_id]['somme_scores_coefs']  /$tab_total[$eleve_id]['nb_coefs'] ,0) : FALSE ; }
          else           { $tab_moyenne_scores_eleve[0][$eleve_id] = ($tab_total[$eleve_id]['nb_scores']) ? round($tab_total[$eleve_id]['somme_scores_simples']/$tab_total[$eleve_id]['nb_scores'],0) : FALSE ; }
          $tab_pourcentage_acquis_eleve[0][$eleve_id] = ($tab_total[$eleve_id]['nb_scores']) ? OutilBilan::calculer_pourcentage_acquisition_items( $tab_total[$eleve_id] , $tab_total[$eleve_id]['nb_scores'] ) : FALSE ;
        }
      }
    }
    if( ($only_etat!='tous') && empty($tab_eval) && !$make_officiel && !$make_brevet ) // Dans le cas d’un bilan officiel, ou d’une récupération pour une fiche brevet, où l’on regarde les élèves d’un groupe un à un, ce ne doit pas être bloquant.
    {
      // Cas où, à cause de la restriction à des items échoués ou réussis, on n’a plus d’évaluation pour tous les élèves
      Json::end( FALSE , 'Aucune évaluation trouvée sur la période '.$date_debut.' ~ '.$date_fin.' en restreignant aux items '.$tab_titre_etat[$only_etat].'.' );
    }
  }
}
else
{
  // Pour pouvoir passer dans la boucle en cas d’appréciation sur le groupe
  foreach($tab_matiere as $matiere_id => $tab)
  {
    $tab_eval[$eleve_id][$matiere_id] = array();
  }
}

/*
  On renseigne (uniquement pour dans certains cas) :
  $tab_moyenne_scores_item[$item_id]
  $tab_pourcentage_acquis_item[$item_id]
  $tab_infos_acquis_item[$item_id]
*/

if( $type_synthese || ($releve_individuel_format=='item') )
{
  foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
  {
    foreach($tab_item as $item_id=>$item_nom)
    {
      $tableau_score_filtre = isset($tab_score_item_eleve[$item_id]) ? array_filter($tab_score_item_eleve[$item_id],'non_vide') : array() ; // Test pour éviter de rares "array_filter() expects parameter 1 to be array, null given"
      $nb_scores = count( $tableau_score_filtre );
      if($nb_scores)
      {
        $somme_scores = array_sum($tableau_score_filtre);
        $tab_acquisitions = OutilBilan::compter_nombre_acquisitions_par_etat( $tableau_score_filtre , 0 /*aff_prop_sans_score*/ );
        $tab_moyenne_scores_item[$item_id]     = round($somme_scores/$nb_scores,0);
        $tab_pourcentage_acquis_item[$item_id] = OutilBilan::calculer_pourcentage_acquisition_items( $tab_acquisitions , $nb_scores );
        $tab_infos_acquis_item[$item_id]       = OutilBilan::afficher_nombre_acquisitions_par_etat( $tab_acquisitions , FALSE /*detail_couleur*/ );
      }
      else
      {
        $tab_moyenne_scores_item[$item_id]     = FALSE;
        $tab_pourcentage_acquis_item[$item_id] = FALSE;
        $tab_infos_acquis_item[$item_id]       = FALSE;
      }
    }
  }
}

/*
  On renseigne (utile pour le tableau de synthèse et le bulletin) :
  $moyenne_moyenne_scores
  $moyenne_pourcentage_acquis
*/
/*
  on pourrait calculer de 2 façons chacune des deux valeurs...
  pour la moyenne des moyennes obtenues par élève : c’est simple car les coefs ont déjà été pris en compte dans le calcul pour chaque élève
  pour la moyenne des moyennes obtenues par item : c’est compliqué car il faudrait repondérer par les coefs éventuels de chaque item
  donc la 1ère technique a été retenue, à défaut d’essayer de calculer les deux et d’en faire la moyenne ;-)
*/

if( $type_synthese || $type_bulletin )
{
  if($item_nb) // Peut valoir 0 dans le cas d’une récupération pour une fiche brevet (il ne faut pas qu’un élève sans rien soit bloquant).
  {
    // $moyenne_moyenne_scores
    $somme  = array_sum($tab_moyenne_scores_eleve[$matiere_id]);
    $nombre = count( array_filter($tab_moyenne_scores_eleve[$matiere_id],'non_vide') );
    $moyenne_moyenne_scores = ($nombre) ? round($somme/$nombre,0) : FALSE ;
    // Pour $moyenne_scores_affichee on n’utilise pas $moyenne_moyenne_scores qui est arrondi.
    // 
    // Sinon, par exemple :
    // - une moyenne est de 59,448275862069... est arrondie à 59 %
    // - une moyenne est de 58,586206896551... est arrondie à 59 %
    // et du coup les moyennes arrondies sont de 11,8 à chaque fois
    // alors qu’en partant des valeurs non arrondies on obtient 11,9 et 11,7.
    // 
    // En contrepartie, cela donne un paradoxe apparent, car les pourcentages arrondis sont affichés dans le tableau de synthèse collective.
    // Du coup, si on les compare au document "notes pour un bulletin", on n’a pas la correspondance avec 11,8 comme on pourrait s’y attendre.
    // Pour autant, ce n’est pas une erreur, cela s’explique simplement par le fait que 59 % est un arrondi.
    $moyenne_scores_affichee = ($nombre) ? sprintf("%04.1f",$somme/$nombre/5) : FALSE ;
    // $moyenne_pourcentage_acquis
    $somme  = array_sum($tab_pourcentage_acquis_eleve[$matiere_id]);
    $nombre = count( array_filter($tab_pourcentage_acquis_eleve[$matiere_id],'non_vide') );
    $moyenne_pourcentage_acquis = ($nombre) ? round($somme/$nombre,0) : FALSE ;
  }
  else
  {
    $moyenne_moyenne_scores     = FALSE ;
    $moyenne_pourcentage_acquis = FALSE ;
    $moyenne_scores_affichee    = FALSE ;
  }
}

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

if( $type_individuel && ($releve_individuel_format=='eleve') )
{
  $nb_lignes_appreciation_intermediaire_par_prof_hors_intitule = ( $make_officiel && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_RUBRIQUE_LONGUEUR']<250) ) ? 1   : 2 ;
  $nb_lignes_appreciation_generale_avec_intitule               = ( $make_officiel && $_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_LONGUEUR'] )       ? 1+6 : 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']['RELEVE_LIGNE_SUPPLEMENTAIRE'] )                 ? 1.3 : 0 ;
  $nb_lignes_legendes                                          = ($legende=='oui') ? 0.5 + 1 + ($retroactif!='non') + ($aff_etat_acquisition) : 0 ;
  $nb_lignes_matiere_intitule_et_marge                         = 1.5 ;
  $nb_lignes_matiere_synthese                                  = $aff_moyenne_scores + $aff_pourcentage_acquis ;
  // Usage d’un tableau intermédiaire pour dénombrer
  $tab_nb_lignes = array();
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    foreach($tab_matiere as $matiere_id => $tab)
    {
      if(isset($tab_eval[$eleve_id][$matiere_id])) // $tab_eval[] utilisé plutôt que $tab_score_eleve_item[] au cas où $calcul_acquisitions=FALSE
      {
        $tab_nb_lignes[$eleve_id][$matiere_id] = $nb_lignes_matiere_intitule_et_marge + count($tab_eval[$eleve_id][$matiere_id],COUNT_NORMAL) + $nb_lignes_matiere_synthese ;
        if( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_RUBRIQUE_LONGUEUR']) && isset($tab_saisie[$eleve_id][$matiere_id]) )
        {
          $tab_nb_lignes[$eleve_id][$matiere_id] += ($nb_lignes_appreciation_intermediaire_par_prof_hors_intitule * count($tab_saisie[$eleve_id][$matiere_id]) ) + 1 ; // + 1 pour "Appréciation / Conseils pour progresser"
        }
      }
    }
  }
  // Calcul des totaux une unique fois par élève
  $tab_nb_lignes_total_eleve = array();
  foreach($tab_nb_lignes as $eleve_id => $tab)
  {
    $tab_nb_lignes_total_eleve[$eleve_id] = array_sum($tab);
  }
  // plus besoin de ce tableau intermédiaire
  unset($tab_nb_lignes);
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Compter le nombre de lignes à afficher par item
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if( $type_individuel && ($releve_individuel_format=='item') )
{
  $nb_lignes_item_intitule_et_marge = 1.5 ;
  $nb_lignes_item_synthese          = $aff_moyenne_scores + $aff_pourcentage_acquis ;
  $tab_nb_lignes_total_item = array();
  // On commence par recenser les items
  foreach($tab_matiere as $matiere_id => $tab)
  {
    if(isset($tab_matiere_item[$matiere_id]))
    {
      foreach($tab_matiere_item[$matiere_id] as $item_id => $item_nom)
      {
        $tab_nb_lignes_total_item[$item_id] = $nb_lignes_item_intitule_et_marge + $nb_lignes_item_synthese ;
      }
    }
  }
  // Puis on passe en revue les notes pour avoir le nombre d’élève par item
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    foreach($tab_matiere as $matiere_id => $tab)
    {
      if(isset($tab_eval[$eleve_id][$matiere_id])) // $tab_eval[] utilisé plutôt que $tab_score_eleve_item[] au cas où $calcul_acquisitions=FALSE
      {
        foreach($tab_eval[$eleve_id][$matiere_id] as $item_id => $tab)
        {
          $tab_nb_lignes_total_item[$item_id] += 1;
        }
      }
    }
  }
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// 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( ($releve_individuel_format=='eleve') && !isset($tab_destinataires) )
{
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    $tab_destinataires[$eleve_id][0] = TRUE ;
  }
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Elaboration du bilan individuel, disciplinaire ou transdisciplinaire, en HTML / PDF / CSV
// ////////////////////////////////////////////////////////////////////////////////////////////////////

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

if($type_individuel)
{
  $annee_decalage = empty($_SESSION['NB_DEVOIRS_ANTERIEURS']) ? 0 : -1 ;
  $date_sql_debut_annee_scolaire = To::jour_debut_annee_scolaire('sql',$annee_decalage); // Date de fin de l’année scolaire précédente
  // Pour un relevé officiel, on force les droits du profil parent pour le PDF, et aussi pour le HTML, en guide de prévisualisation, pour ne pas être surpris lors de l’impression finale.
  $forcer_profil = $make_officiel ? 'TUT' : NULL ;
  Html::$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 );
  $aff_codes_notation      = ( $cases_auto || $cases_nb ) ? TRUE : FALSE ;
  $aff_anciennete_notation = ( $aff_codes_notation && ($retroactif!='non') ) ? TRUE : FALSE ;
  if($make_html)
  {
    $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      = (!empty($tab_saisie_avant))                          ? '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::$couleur = $couleur ;
    $html  = $affichage_direct ? '' : '<style>'.$_SESSION['CSS'].'</style>'.NL;
    $html .= $make_officiel    ? '' : '<h1>'.$bilan_intro.$bilan_titre_html.'</h1>'.NL;
    $html .= $make_officiel    ? '' : '<h2>'.$texte_periode_html.'</h2>'.NL;
    $html .= ($info_details || $bouton_print_test || $bouton_import_csv) ? '<div class="ti">'.$info_details.$bouton_print_test.$bouton_import_csv.'</div>'.NL : '' ;
    $bilan_colspan = $cases_nb + 2 ; // sera modifié si adaptation automatique du nb de colonnes
    $num_colonne_score = ($longueur_ref_max) ? $bilan_colspan : $bilan_colspan-1 ; // idem
    $tfoot_td_nu  = ($longueur_ref_max) ? '<td class="nu">&nbsp;</td>'       : '' ;
    $thead_th_ref = ($longueur_ref_max) ? '<th data-sorter="text">Ref.</th>' : '' ;
    $separation = (count($tab_eleve_infos)>1) ? '<hr class="breakafter">'.NL : '' ;
    $html_javascript = '';
    $tab_legende = array(
      'codes_notation'      => $aff_codes_notation ,
      'anciennete_notation' => $aff_anciennete_notation ,
      'score_bilan'         => $aff_etat_acquisition ,
      'highlight'           => $highlight_id ,
    );
  }
  if($make_csv)
  {
    $csv = new CSV();
    $csv->add('Bilan '.$bilan_titre_pdf_csv_json , 1 )->add( 'Exploitation tableur' , 1 )->add( $groupe_nom , 1 )->add( $texte_periode_pdf_csv , 2 );
    $tab_csv_head = array('nb items');
    if($aff_moyenne_scores)
    {
      $tab_csv_head[] ='moy. scores '.$info_ponderation_courte;
    }
    if( $aff_pourcentage_acquis )
    {
      $tab_csv_head[] ='% items acquis';
    }
  }
  if($make_json)
  {
    $tab_json = array(
      'parametres' => array(
        'objet'      => 'Bilan '.$bilan_titre_pdf_csv_json,
        'groupe'     => $groupe_nom,
        'date_debut' => $date_debut,
        'date_fin'   => $date_fin,
      ),
      'matiere' => array(),
      'item'    => array(),
      'eleve'   => array(),
      'score'   => array(),
    );
  }
  if($make_pdf)
  {
    // Appel de la classe et définition de qqs variables supplémentaires pour la mise en page PDF
    $pdf = new PDF_item_releve( $make_officiel , 'A4' /*page_size*/ , $orientation , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond , $legende , !empty($is_test_impression) /*filigrane*/ );
    if($make_officiel)
    {
      $tab_archive['user'][0][] = array( '__construct' , array( $make_officiel , 'A4' /*page_size*/ , $orientation , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , 'oui' /*couleur*/ , $fond , $legende , !empty($is_test_impression) /*filigrane*/ , $tab_archive['session'] ) );
    }
  }
  /*
   * ********************************
   * Cas d’une présentation par élève
   * ********************************
   * Usage le plus courant, le seul envisagé et disponible pendant des années.
   * Un bilan officiel est toujours présenté par élève.
   */
  if($releve_individuel_format=='eleve')
  {
    if($make_pdf)
    {
      $lignes_nb = ($releve_modele!='multimatiere') ? array_sum($tab_nb_lignes_total_eleve) : 0 ;
      $pdf->initialiser( $releve_modele , $releve_individuel_format , $aff_etat_acquisition , $aff_codes_notation , $aff_anciennete_notation , $longueur_ref_max , $cases_nb , $cases_largeur , $lignes_nb , $eleve_nb , $pages_nb );
    }
    // Pour chaque élève...
    foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
    {
      extract($tab_eleve);  // $eleve_INE $eleve_nom $eleve_prenom $date_naissance $eleve_genre $eleve_id_gepi
      $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
        $is_appreciation_generale_enregistree = isset($tab_saisie[$eleve_id][0]) ? TRUE : FALSE ;
        $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_eval[$eleve_id]))
        {
          // Intitulé
          if($make_html) { $html .= (!$make_officiel) ? $separation.'<h2>'.html($groupe_nom).' - '.html($eleve_nom_prenom).'</h2>'.NL : '' ; }
          if($make_csv)  { $csv->add( $eleve_nom_prenom )->add( $tab_csv_head , 1 ); }
          if($make_json)
          {
            $tab_json['eleve'][$eleve_id] = array(
              'nom'    => $eleve_nom,
              'prenom' => $eleve_prenom,
            );
          }
          if($make_pdf)
          {
            if($is_archive)
            {
              $tab_archive['user'][$eleve_id]['image_md5'] = array();
              $tab_archive['user'][$eleve_id][] = array( 'initialiser' , array( $releve_modele , $releve_individuel_format , $aff_etat_acquisition , $aff_codes_notation , $aff_anciennete_notation , $longueur_ref_max , $cases_nb , $cases_largeur , $lignes_nb , 1 /*eleve_nb*/ , $pages_nb ) );
            }
            $eleve_nb_lignes  = $tab_nb_lignes_total_eleve[$eleve_id] + $nb_lignes_appreciation_generale_avec_intitule + $nb_lignes_assiduite + $nb_lignes_prof_principal + $nb_lignes_supplementaires;
            $tab_infos_entete = (!$make_officiel) ?
              array(
                'bilan_titre'   => $bilan_titre_pdf_csv_json ,
                'texte_periode' => $texte_periode_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 ,
              ) ;
            $pdf->entete_format_eleve( $pages_nb , $tab_infos_entete , $eleve_nom_prenom , $eleve_INE , $eleve_nb_lignes );
            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_format_eleve' , array( $pages_nb , $tab_infos_entete , $eleve_nom_prenom , $eleve_INE , $eleve_nb_lignes ) );
            }
          }
          for( $ordre_passage_blocs=1 ; $ordre_passage_blocs<3 ; $ordre_passage_blocs++ )
          {
            if( ( ($ordre_passage_blocs==1) && ( !$make_officiel || ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_POSITION']=='apres') ) ) || ( ($ordre_passage_blocs==2) && $make_officiel && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_POSITION']=='avant') ) )
            {
              // Pour chaque matiere...
              foreach($tab_matiere as $matiere_id => $tab)
              {
                extract($tab); // $matiere_nom $matiere_nb_demandes
                if( (!$make_officiel) || (($make_action=='modifier')&&(in_array($matiere_id,$tab_matiere_id))) || ($make_action=='tamponner') || (($make_action=='examiner')&&(in_array($matiere_id,$tab_matiere_id))) || ($make_action=='consulter') || ($make_action=='imprimer') )
                {
                  // Si cet élève a été évalué dans cette matière...
                  if(isset($tab_eval[$eleve_id][$matiere_id]))
                  {
                    if( ($make_html) || ($make_pdf) )
                    {
                      if($cases_auto)
                      {
                        // Déterminer le nombre de colonnes optimal pour cette matière et cet élève
                        $cases_nb = 0;
                        foreach($tab_eval[$eleve_id][$matiere_id] as $item_id => $tab_devoirs)
                        {
                          $devoirs_nb = count($tab_devoirs);
                          $cases_nb = max( $cases_nb , $devoirs_nb );
                        }
                        $cases_nb = min( $cases_nb , NB_CASES_MAX );
                        $cases_largeur = max( 5 , min( 12-$cases_nb , 8 ) );
                        $bilan_colspan = $cases_nb + 2 ;
                        $num_colonne_score = ($longueur_ref_max) ? $bilan_colspan : $bilan_colspan-1 ;
                      }
                      $item_matiere_nb = count($tab_eval[$eleve_id][$matiere_id]);
                      if( ($make_pdf) && ( ($releve_modele!='matiere') || $cases_auto ) )
                      {
                        $matiere_lignes_nb = $item_matiere_nb + $aff_moyenne_scores + $aff_pourcentage_acquis ;
                        $pdf->transdisciplinaire_ligne_matiere( $matiere_nom , $matiere_lignes_nb , $cases_nb , $cases_largeur );
                        if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'transdisciplinaire_ligne_matiere' , array( $matiere_nom , $matiere_lignes_nb , $cases_nb , $cases_largeur ) ); }
                      }
                      if($make_html)
                      {
                        $html .= '<h3>'.html($matiere_nom).'</h3>'.NL;
                        // On passe au tableau
                        $html_table_head = '<thead><tr>'.$thead_th_ref.'<th data-sorter="text">Nom de l’item</th>';
                        if($cases_nb)
                        {
                          for($num_case=0;$num_case<$cases_nb;$num_case++)
                          {
                            $html_table_head .= '<th data-sorter="false"></th>';  // Pas de colspan sinon pb avec le tri
                          }
                        }
                        $html_table_head .= ($aff_etat_acquisition) ? '<th data-sorter="FromData" data-empty="bottom" data-sort-initial-order="'.$releve_tri.'">score</th>' : '' ;
                        $html_table_head .= '<th class="nu"></th></tr></thead>'.NL;
                        $html_table_body = '<tbody>'.NL;
                      }
                      if($make_csv)
                      {
                        $csv->add( $matiere_nom )->add( $item_matiere_nb );
                      }
                      if($make_json)
                      {
                        $tab_json['matiere'][$matiere_id] = $matiere_nom;
                      }
                      // Pour chaque item...
                      foreach($tab_eval[$eleve_id][$matiere_id] as $item_id => $tab_devoirs)
                      {
                        $score = ($calcul_acquisitions) ? $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id] : FALSE ;
                        extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_comm $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
                        // cases référence et nom
                        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_comm)
                        {
                          $image_comm  = ($item_comm) ? 'oui' : 'non' ;
                          $title_comm  = ($item_comm) ? $item_comm : 'Sans commentaire.' ;
                          $texte_comm  = '<img src="./_img/etat/comm_'.$image_comm.'.png"'.infobulle($title_comm).'"> ';
                        }
                        if($make_html)
                        {
                          if($aff_lien)
                          {
                            $texte_lien_avant = ($item_lien) ? '<a target="_blank" rel="noopener noreferrer" href="'.html($item_lien).'">' : '';
                            $texte_lien_apres = ($item_lien) ? '</a>' : '';
                          }
                          if($highlight_id)
                          {
                            $texte_fluo_avant = ($highlight_id!=$item_id) ? '' : '<span class="fluo">';
                            $texte_fluo_apres = ($highlight_id!=$item_id) ? '' : '</span>';
                          }
                          $item_matiere_id = ($matiere_id) ? $matiere_id : $tab_item_matiere[$item_id] ;
                          $icones_action = ( ($_SESSION['USER_PROFIL_TYPE']=='professeur') && in_array($item_matiere_id,$tab_prof_matieres_id) && ($origine!='evaluation_ponctuelle') )
                                         ? '<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>'; }
                          }
                          $td_actions = '<td class="nu" data-matiere="'.$item_matiere_id.'" data-item="'.$item_id.'" data-eleve="'.$eleve_id.'">'.$icones_action.'</td>';
                          $td_ref = ($longueur_ref_max) ? '<td>'.$item_ref.'</td>' : '' ;
                          $html_table_body .= '<tr>'.$td_ref.'<td>'.$texte_coef.$texte_s2016.$texte_comm.$texte_lien_avant.$texte_fluo_avant.html($item_nom).$texte_fluo_apres.$texte_lien_apres.'</td>';
                        }
                        if($make_pdf)
                        {
                          $item_texte = $texte_coef.$texte_s2016.$item_nom;
                          $pdf->debut_ligne_item( $item_ref , $item_texte );
                          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'debut_ligne_item' , array( $item_ref , $item_texte ) ); }
                        }
                        if($make_json)
                        {
                          $tab_json['item'][$item_id] = array(
                            'matiere_id' => $item_matiere_id,
                            'ref'        => $item_ref,
                            'nom'        => $item_nom,
                          );
                        }
                        // cases d’évaluations
                        $devoirs_nb = count($tab_devoirs);
                        // on passe en revue les cases disponibles et on remplit en fonction des évaluations disponibles
                        if($cases_nb)
                        {
                          $decalage = $devoirs_nb - $cases_nb;
                          for($i=0;$i<$cases_nb;$i++)
                          {
                            // on doit remplir une case
                            if($decalage<0)
                            {
                              // il y a moins d’évaluations que de cases à remplir : on met un score dispo ou une case blanche si plus de score dispo
                              if($i<$devoirs_nb)
                              {
                                extract($tab_devoirs[$i]);  // $note $date $info
                                if($date<$date_sql_debut_annee_scolaire)
                                {
                                  $pdf_bg = 'prev_year';
                                  $td_class = ' class="prev_year"';
                                  $fond_gris = TRUE;
                                }
                                elseif($date<$date_sql_debut)
                                {
                                  $pdf_bg = 'prev_date';
                                  $td_class = ' class="prev_date"';
                                  $fond_gris = TRUE;
                                }
                                else
                                {
                                  $pdf_bg = '';
                                  $td_class = '';
                                  $fond_gris = FALSE;
                                }
                                if($make_html) { $html_table_body .= '<td'.$td_class.'>'.Html::note_image($note,$date,$info,TRUE,$fond_gris).'</td>'; }
                                if($make_pdf)  { $pdf->afficher_note_lomer( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ); }
                                if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'afficher_note_lomer' , array( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ) ); }
                              }
                              else
                              {
                                if($make_html) { $html_table_body .= '<td>&nbsp;</td>'; }
                                if($make_pdf)  { $pdf->afficher_note_lomer( '' /*note*/ , 1 /*border*/ , 0 /*br*/ ); }
                                if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'afficher_note_lomer' , array( '' /*note*/ , 1 /*border*/ , 0 /*br*/ ) ); }
                              }
                            }
                            // il y a plus d’évaluations que de cases à remplir : on ne prend que les dernières (décalage d’indice)
                            else
                            {
                              extract($tab_devoirs[$i+$decalage]);  // $note $date $info
                              if($date<$date_sql_debut_annee_scolaire)
                              {
                                $pdf_bg = 'prev_year';
                                $td_class = ' class="prev_year"';
                                $fond_gris = TRUE;
                              }
                              elseif($date<$date_sql_debut)
                              {
                                $pdf_bg = 'prev_date';
                                $td_class = ' class="prev_date"';
                                $fond_gris = TRUE;
                              }
                              else
                              {
                                $pdf_bg = '';
                                $td_class = '';
                                $fond_gris = FALSE;
                              }
                              if($make_html) { $html_table_body .= '<td'.$td_class.'>'.Html::note_image($note,$date,$info,TRUE,$fond_gris).'</td>'; }
                              if($make_pdf)  { $pdf->afficher_note_lomer( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ); }
                              if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'afficher_note_lomer' , array( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ) ); }
                            }
                          }
                        }
                        // affichage du bilan de l’item
                        if($aff_etat_acquisition)
                        {
                          if($make_html) { $html_table_body .= Html::td_score( $score , 'score' , '' /*pourcent*/ , '' /*checkbox_val*/ ); }
                          if($make_pdf)  { $pdf->afficher_score_bilan( $score , 1 /*br*/ ); }
                          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'afficher_score_bilan' , array( $score , 1 /*br*/ ) ); }
                          if($make_json) { $tab_json['score'][$eleve_id][$item_id] = $score; }
                        }
                        else
                        {
                          if($make_pdf)  { $pdf->passage_ligne_suivante(); }
                          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'passage_ligne_suivante' , array() ); }
                        }
                        if($make_html)
                        {
                          $html_table_body .= $td_actions.'</tr>'.NL;
                        }
                      }
                      if($make_html)
                      {
                        $html_table_body .= '</tbody>'.NL;
                        $html_table_foot = '';
                      }
                      // affichage des bilans des scores
                      if($eleve_id && $aff_etat_acquisition)
                      {
                        // ... un pour la moyenne des pourcentages d’acquisition
                        if( $aff_moyenne_scores )
                        {
                          if($tab_moyenne_scores_eleve[$matiere_id][$eleve_id] !== FALSE)
                          {
                            $pourcentage = $tab_moyenne_scores_eleve[$matiere_id][$eleve_id].'%';
                            $texte_bilan = ($conversion_sur_20) ? $pourcentage.' soit '.sprintf("%04.1f",$tab_moyenne_scores_eleve[$matiere_id][$eleve_id]/5).'/20' : $pourcentage ;
                          }
                          else
                          {
                            $pourcentage = '';
                            $texte_bilan = '---';
                          }
                          if($make_html) { $html_table_foot .= '<tr>'.$tfoot_td_nu.'<td colspan="'.$bilan_colspan.'">Moyenne '.$info_ponderation_complete.' des scores d’acquisitions : '.$texte_bilan.'</td><td class="nu"></td></tr>'.NL; }
                          if($make_pdf)  { $pdf->ligne_synthese('Moyenne '.$info_ponderation_complete.' des scores d’acquisitions : '.$texte_bilan); }
                          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_synthese' , array( 'Moyenne '.$info_ponderation_complete.' des scores d’acquisitions : '.$texte_bilan ) ); }
                          if($make_csv)  { $csv->add( $pourcentage ); }
                        }
                        // ... un pour le nombre d’items considérés acquis ou pas
                        if( $aff_pourcentage_acquis )
                        {
                          if($tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] !== FALSE)
                          {
                            $pourcentage = $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id].'%';
                            $texte_bilan  = '('.$tab_infos_acquis_eleve[$matiere_id][$eleve_id].') : '.$pourcentage;
                            $texte_bilan .= ($conversion_sur_20) ? ' soit '.sprintf("%04.1f",$tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id]/5).'/20' : '' ;
                          }
                          else
                          {
                            $pourcentage = '';
                            $texte_bilan = '---';
                          }
                          if($make_html) { $html_table_foot .= '<tr>'.$tfoot_td_nu.'<td colspan="'.$bilan_colspan.'">Pourcentage d’items acquis '.$texte_bilan.'</td><td class="nu"></td></tr>'.NL; }
                          if($make_pdf)  { $pdf->ligne_synthese('Pourcentage d’items acquis '.$texte_bilan); }
                          if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'ligne_synthese' , array( 'Pourcentage d’items acquis '.$texte_bilan ) ); }
                          if($make_csv)  { $csv->add( $pourcentage ); }
                        }
                      }
                      if( $make_html && empty($is_appreciation_groupe) )
                      {
                        $html_table_foot = ($html_table_foot) ? '<tfoot>'.NL.$html_table_foot.'</tfoot>'.NL : '';
                        $html .= '<table id="table'.$eleve_id.'x'.$matiere_id.'" class="bilan hsort">'.NL.$html_table_head.$html_table_foot.$html_table_body.'</table>'.NL;
                        $html_javascript .= '$("#table'.$eleve_id.'x'.$matiere_id.'").tablesorter();';
                        if( $aff_etat_acquisition && ($releve_tri!='none') )
                        {
                          $html_javascript .= '$("#table'.$eleve_id.'x'.$matiere_id.'").find("th:eq('.$num_colonne_score.')").trigger("sort");';
                        }
                      }
                      if($make_csv)
                      {
                        $csv->add( NULL , 1 );
                      }
                      if( $make_html && $make_officiel && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_RUBRIQUE_LONGUEUR']) )
                      {
                        // Relevé de notes - Info saisies périodes antérieures
                        $appreciations_avant = '';
                        if(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();
                            foreach($tab_prof as $prof_id => $tab)
                            {
                              extract($tab);  // $prof_info $appreciation $note
                              $tab_ligne[$prof_id] = html('['.$prof_info.'] '.$appreciation);
                            }
                            $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">'.'<b>'.html($tab_periode_avant[$periode_id]).' :'.'</b>'.'<br>'.implode('<br>',$tab_ligne).'</div>';
                          }
                          $appreciations_avant = '<tr><td class="avant">'.implode('&nbsp;&nbsp;&nbsp;',$tab_periode_liens).implode('',$tab_periode_textes).'</td></tr>'.NL;
                        }
                        // Relevé de notes - Appréciations intermédiaires (HTML)
                        $appreciations = '';
                        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 l’appréciation sur la classe ?
                            {
                              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>'; }
                              }
                              $appreciations .= '<tr id="appr_'.$matiere_id.'_'.$prof_id.'"><td 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' ;
                            $appreciations .= '<tr id="appr_'.$matiere_id.'_'.$_SESSION['USER_ID'].'"><td class="now"><div class="hc"><button type="button" class="ajouter">Ajouter une appréciation'.$texte_classe.'.</button></div></td></tr>'.NL;
                          }
                        }
                        $html .= ($appreciations_avant || $appreciations) ? '<table style="width:900px" class="bilan"><tbody>'.NL.$appreciations_avant.$appreciations.'</tbody></table>'.NL : '' ;
                      }
                    }
                    // Examen de présence des appréciations intermédiaires
                    if( ($make_action=='examiner') && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_RUBRIQUE_LONGUEUR']) && (!isset($tab_saisie[$eleve_id][$matiere_id])) )
                    {
                      $tab_resultat_examen[$matiere_nom][] = 'Absence d’appréciation pour '.html($eleve_nom_prenom);
                    }
                    // Impression des appréciations intermédiaires (PDF)
                    if( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_RUBRIQUE_LONGUEUR']) && (isset($tab_saisie[$eleve_id][$matiere_id])) )
                    {
                      $pdf->appreciation_rubrique( $tab_saisie[$eleve_id][$matiere_id] );
                      if($is_archive){ $tab_archive['user'][$eleve_id][] = array( 'appreciation_rubrique' , array( $tab_saisie[$eleve_id][$matiere_id] ) ); }
                    }
                  }
                }
              }
            }
            if( ( ($ordre_passage_blocs==2) && ( !$make_officiel || ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_POSITION']=='apres') ) ) || ( ($ordre_passage_blocs==1) && $make_officiel && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_POSITION']=='avant') ) )
            {
              // Relevé de notes - Synthèse générale
              if( $make_officiel && ($_SESSION['OFFICIEL']['RELEVE_APPRECIATION_GENERALE_LONGUEUR']) && ( ($make_action=='tamponner') || ($make_action=='consulter') ) )
              {
                if($make_html)
                {
                  $html .= '<h3>Synthèse générale</h3>'.NL.'<table style="width:900px" class="bilan"><tbody>'.NL;
                  // Relevé de notes - 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();
                      foreach($tab_prof as $prof_id => $tab)
                      {
                        extract($tab);  // $prof_info $appreciation $note
                        $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_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">'.'<b>'.html($tab_periode_avant[$periode_id]).' :'.'</b>'.'<br>'.implode('<br>',$tab_ligne).'</div>';
                    }
                    $html .= '<tr><td class="avant">'.implode('&nbsp;&nbsp;&nbsp;',$tab_periode_liens).implode('',$tab_periode_textes).'</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>' : '' ;
                  // Relevé de notes - Appréciation générale
                  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 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 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 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']['RELEVE_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
              if( ($make_action=='imprimer') && ($_SESSION['OFFICIEL']['RELEVE_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;
                }
                $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 );
                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 ) );
                }
              }
              $tab_pdf_lignes_additionnelles = array();
              // Relevé de notes - Absences et retard
              if( $make_officiel && ($affichage_assiduite) && empty($is_appreciation_groupe) )
              {
                $texte_assiduite = texte_ligne_assiduite($tab_assiduite[$eleve_id]);
                if($make_html)
                {
                  $html .= '<div class="i">'.$texte_assiduite.'</div>'.NL;
                }
                elseif($make_action=='imprimer')
                {
                  $tab_pdf_lignes_additionnelles[] = $texte_assiduite;
                }
              }
              // Relevé de notes - Professeurs principaux
              if( $make_officiel && ($affichage_prof_principal) )
              {
                if($make_html)
                {
                  $html .= '<div class="i">'.$texte_prof_principal.'</div>'.NL;
                }
                elseif($make_action=='imprimer')
                {
                  $tab_pdf_lignes_additionnelles[] = $texte_prof_principal;
                }
              }
              // Relevé de notes - Ligne additionnelle
              if( ($make_action=='imprimer') && ($nb_lignes_supplementaires) )
              {
                $tab_pdf_lignes_additionnelles[] = $_SESSION['OFFICIEL']['RELEVE_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 ) ); }
              }
              // Relevé de notes - Date de naissance
              if( $make_officiel && ($date_naissance) && ( ($make_html) || ($make_graph) ) )
              {
                $html .= '<div class="i">'.To::texte_ligne_naissance($date_naissance).'</div>'.NL;
              }
            }
          }
          // Relevé de notes - Légende
          if( ( ($make_html) || ($make_pdf) ) && ($legende=='oui') && empty($is_appreciation_groupe) )
          {
            if($make_html) { $html .= Html::legende($tab_legende); }
            if($make_pdf)  { $pdf->legende(); }
            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 );
          }
        }
      }
    }
  }
  /*
   * *******************************
   * Cas d’une présentation par item
   * *******************************
   * Usage marginal (nouvelle fonctionnalité août 2014).
   * Un bilan officiel n’est jamais présenté par item.
   */
  elseif($releve_individuel_format=='item')
  {
    if($make_pdf)
    {
      $lignes_nb = array_sum($tab_nb_lignes_total_item) + ($matiere_nb*1.5) ;
      $pdf->initialiser( $releve_modele , $releve_individuel_format , $aff_etat_acquisition , $aff_codes_notation , $aff_anciennete_notation , $longueur_ref_max , $cases_nb , $cases_largeur , $lignes_nb , $item_nb , $pages_nb );
      $pdf->entete_format_item( $bilan_titre_pdf_csv_json , $texte_periode_pdf_csv , $groupe_nom );
    }
    // Pour chaque matiere...
    foreach($tab_matiere as $matiere_id => $tab)
    {
      extract($tab); // $matiere_nom $matiere_nb_demandes
      if(isset($tab_matiere_item[$matiere_id]))
      {
        if($make_html) { $html .= $separation.'<h2>'.html($groupe_nom.' - '.$matiere_nom).'</h2>'.NL; }
        // Pour chaque item...
        foreach($tab_matiere_item[$matiere_id] as $item_id => $item_nom)
        {
          if( ($make_html) || ($make_pdf) )
          {
            if($cases_auto)
            {
              // Déterminer le nombre de colonnes optimal pour cette matière et cet item
              $cases_nb = 0;
              // Pour chaque élève...
              foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
              {
                // Si cet élève a été évalué sur cet item...
                if(isset($tab_eval[$eleve_id][$matiere_id][$item_id]))
                {
                  $tab_devoirs = $tab_eval[$eleve_id][$matiere_id][$item_id];
                  $devoirs_nb = count($tab_devoirs);
                  $cases_nb = max( $cases_nb , $devoirs_nb );
                }
              }
              $cases_nb = min( $cases_nb , NB_CASES_MAX );
              $cases_largeur = max( 5 , min( 12-$cases_nb , 8 ) );
              $bilan_colspan = $cases_nb + 2 ;
              $num_colonne_score = ($longueur_ref_max) ? $bilan_colspan : $bilan_colspan-1 ;
            }
          }
          extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
          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_comm)
          {
            $image_comm  = ($item_comm) ? 'oui' : 'non' ;
            $title_comm  = ($item_comm) ? $item_comm : 'Sans commentaire.' ;
            $texte_comm  = '<img src="./_img/etat/comm_'.$image_comm.'.png"'.infobulle($title_comm).'> ';
          }
          if($make_html)
          {
            if($aff_lien)
            {
              $texte_lien_avant = ($item_lien) ? '<a target="_blank" rel="noopener noreferrer" href="'.html($item_lien).'">' : '';
              $texte_lien_apres = ($item_lien) ? '</a>' : '';
            }
            if($highlight_id)
            {
              $texte_fluo_avant = ($highlight_id!=$item_id) ? '' : '<span class="fluo">';
              $texte_fluo_apres = ($highlight_id!=$item_id) ? '' : '</span>';
            }
          }
          // Intitulé
          $texte_item = ($longueur_ref_max) ? $item_ref.' - ' : '' ;
          if($make_pdf)
          {
            $pdf->format_item_ligne_item( $texte_item.$texte_coef.$texte_s2016.$item_nom , $tab_nb_lignes_total_item[$item_id] /*lignes_nb*/ , $cases_nb , $cases_largeur );
          }
          if($make_html)
          {
            $html .= $separation.'<h3>'.$texte_item.$texte_coef.$texte_s2016.$texte_comm.$texte_lien_avant.$texte_fluo_avant.html($item_nom).$texte_fluo_apres.$texte_lien_apres.'</h3>'.NL;
            // On passe au tableau
            $html_table_head = '<thead><tr><th data-sorter="text">Élève</th>';
            if($cases_nb)
            {
              for($num_case=0;$num_case<$cases_nb;$num_case++)
              {
                $html_table_head .= '<th data-sorter="false"></th>';  // Pas de colspan sinon pb avec le tri
              }
            }
            $html_table_head .= ($aff_etat_acquisition) ? '<th data-sorter="FromData" data-empty="bottom" data-sort-initial-order="'.$releve_tri.'">score</th>' : '' ;
            $html_table_head .= '<th class="nu"></th></tr></thead>'.NL;
            $html_table_body = '<tbody>'.NL;
          }
          // Pour chaque élève...
          foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
          {
            // Si cet élève a été évalué sur cet item...
            if(isset($tab_eval[$eleve_id][$matiere_id][$item_id]))
            {
              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);
              // un élève ne peut pas passer par ici, donc pas d’icone de demande d’évaluation
              $item_matiere_id = ($matiere_id) ? $matiere_id : $tab_item_matiere[$item_id] ;
              $icones_action = ( ($_SESSION['USER_PROFIL_TYPE']=='professeur') && in_array($item_matiere_id,$tab_prof_matieres_id) && ($origine!='evaluation_ponctuelle') )
                             ? '<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>'
                             : '' ;
              $td_actions = '<td class="nu" data-matiere="'.$item_matiere_id.'" data-item="'.$item_id.'" data-eleve="'.$eleve_id.'">'.$icones_action.'</td>';
              $html_table_body .= '<tr><td>'.html($eleve_nom_prenom).'</td>';
              if($make_pdf)
              {
                $pdf->debut_ligne_eleve($eleve_nom_prenom);
              }
              // cases d’évaluations
              $tab_devoirs = $tab_eval[$eleve_id][$matiere_id][$item_id];
              $devoirs_nb = count($tab_devoirs);
              // on passe en revue les cases disponibles et on remplit en fonction des évaluations disponibles
              if($cases_nb)
              {
                $decalage = $devoirs_nb - $cases_nb;
                for($i=0;$i<$cases_nb;$i++)
                {
                  // on doit remplir une case
                  if($decalage<0)
                  {
                    // il y a moins d’évaluations que de cases à remplir : on met un score dispo ou une case blanche si plus de score dispo
                    if($i<$devoirs_nb)
                    {
                      extract($tab_devoirs[$i]);  // $note $date $info
                      if($date<$date_sql_debut_annee_scolaire)
                      {
                        $pdf_bg = 'prev_year';
                        $td_class = ' class="prev_year"';
                        $fond_gris = TRUE;
                      }
                      elseif($date<$date_sql_debut)
                      {
                        $pdf_bg = 'prev_date';
                        $td_class = ' class="prev_date"';
                        $fond_gris = TRUE;
                      }
                      else
                      {
                        $pdf_bg = '';
                        $td_class = '';
                        $fond_gris = FALSE;
                      }
                      if($make_html) { $html_table_body .= '<td'.$td_class.'>'.Html::note_image($note,$date,$info,TRUE,$fond_gris).'</td>'; }
                      if($make_pdf)  { $pdf->afficher_note_lomer( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ); }
                    }
                    else
                    {
                      if($make_html) { $html_table_body .= '<td>&nbsp;</td>'; }
                      if($make_pdf)  { $pdf->afficher_note_lomer( '' /*note*/ , 1 /*border*/ , 0 /*br*/ ); }
                    }
                  }
                  // il y a plus d’évaluations que de cases à remplir : on ne prend que les dernières (décalage d’indice)
                  else
                  {
                    extract($tab_devoirs[$i+$decalage]);  // $note $date $info
                    if($date<$date_sql_debut_annee_scolaire)
                    {
                      $pdf_bg = 'prev_year';
                      $td_class = ' class="prev_year"';
                      $fond_gris = TRUE;
                    }
                    elseif($date<$date_sql_debut)
                    {
                      $pdf_bg = 'prev_date';
                      $td_class = ' class="prev_date"';
                      $fond_gris = TRUE;
                    }
                    else
                    {
                      $pdf_bg = '';
                      $td_class = '';
                      $fond_gris = FALSE;
                    }
                    if($make_html) { $html_table_body .= '<td'.$td_class.'>'.Html::note_image($note,$date,$info,TRUE,$fond_gris).'</td>'; }
                    if($make_pdf)  { $pdf->afficher_note_lomer( $note , 1 /*border*/ , 0 /*br*/ , $pdf_bg ); }
                  }
                }
              }
              // affichage du bilan de l’item
              if($aff_etat_acquisition)
              {
                $score = $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id];
                // $score = isset($tab_score_eleve_item[$eleve_id][$matiere_id][$item_id]) ? $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id] : FALSE ;
                if($make_html) { $html_table_body .= Html::td_score( $score , 'score' , '' /*pourcent*/ , '' /*checkbox_val*/ ); }
                if($make_pdf)  { $pdf->afficher_score_bilan( $score , 1 /*br*/ ); }
              }
              else
              {
                if($make_pdf)  { $pdf->SetXY( $pdf->marge_gauche , $pdf->GetY()+$pdf->cases_hauteur ); }
              }
              if($make_html)
              {
                $html_table_body .= $td_actions.'</tr>'.NL;
              }
            }
          }
          if($make_html)
          {
            $html_table_body .= '</tbody>'.NL;
            $html_table_foot = '';
          }
          // affichage des bilans des scores
          if($aff_etat_acquisition)
          {
            // ... un pour la moyenne des pourcentages d’acquisition
            if( $aff_moyenne_scores )
            {
              if($tab_moyenne_scores_item[$item_id] !== FALSE)
              {
                $texte_bilan  = $tab_moyenne_scores_item[$item_id].'%';
                $texte_bilan .= ($conversion_sur_20) ? ' soit '.sprintf("%04.1f",$tab_moyenne_scores_item[$item_id]/5).'/20' : '' ;
              }
              else
              {
                $texte_bilan = '---';
              }
              if($make_html) { $html_table_foot .= '<tr><td colspan="'.$bilan_colspan.'">Moyenne des scores d’acquisitions : '.$texte_bilan.'</td><td class="nu"></td></tr>'.NL; } // indication de pondération inopportune
              if($make_pdf)  { $pdf->ligne_synthese('Moyenne des scores d’acquisitions : '.$texte_bilan); } // indication de pondération inopportune
            }
            // ... un pour le nombre d’items considérés acquis ou pas
            if( $aff_pourcentage_acquis )
            {
              if($tab_pourcentage_acquis_item[$item_id] !== FALSE)
              {
                $texte_bilan  = '('.$tab_infos_acquis_item[$item_id].') : '.$tab_pourcentage_acquis_item[$item_id].'%';
                $texte_bilan .= ($conversion_sur_20) ? ' soit '.sprintf("%04.1f",$tab_pourcentage_acquis_item[$item_id]/5).'/20' : '' ;
              }
              else
              {
                $texte_bilan = '---';
              }
              if($make_html) { $html_table_foot .= '<tr><td colspan="'.$bilan_colspan.'">Pourcentage d’items acquis '.$texte_bilan.'</td><td class="nu"></td></tr>'.NL; }
              if($make_pdf)  { $pdf->ligne_synthese('Pourcentage d’items acquis '.$texte_bilan); }
            }
          }
          if($make_html)
          {
            $html_table_foot = ($html_table_foot) ? '<tfoot>'.NL.$html_table_foot.'</tfoot>'.NL : '';
            $html .= '<table id="table'.$matiere_id.'x'.$item_id.'" class="bilan hsort">'.NL.$html_table_head.$html_table_foot.$html_table_body.'</table>'.NL;
            $html_javascript .= '$("#table'.$matiere_id.'x'.$item_id.'").tablesorter();';
            if( $aff_etat_acquisition && ($releve_tri!='none') )
            {
              $html_javascript .= '$("#table'.$matiere_id.'x'.$item_id.'").find("th:eq('.$num_colonne_score.')").trigger("sort");';
            }
          }
        }
        // Relevé de notes - Légende
        if( ( ($make_html) || ($make_pdf) ) && ($legende=='oui') )
        {
          if($make_html) { $html .= Html::legende($tab_legende); }
          if($make_pdf)  { $pdf->legende(); }
        }
      }
    }
  }
  // Ajout du javascript en fin de fichier
  if($make_html)
  {
    $script = $affichage_direct ? $html_javascript : 'function tri(){'.$html_javascript.'}' ;
    if( !$make_officiel && ($_SESSION['USER_PROFIL_TYPE']=='professeur') )
    {
      $script .= 'var CSRF = "'.$CSRF_eval_eclair.'";'; // Pour les évaluations à la volée.
    }
    $html .= '<script>'.$script.'</script>'.NL;
  }
  // On enregistre les sorties HTML et PDF et CSV
  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 ); }
  if($make_csv)  { FileSystem::ecrire_objet_csv( CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','individuel',$fichier_nom).'.csv'  , $csv ); }
  if($make_json) { FileSystem::ecrire_fichier(   CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','individuel',$fichier_nom).'.json' , json_encode($tab_json) ); }
}

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

if($type_synthese)
{
  // start HTML
  Html::$couleur = $couleur ;
  Html::$afficher_score = Outil::test_user_droit_specifique($_SESSION['DROIT_VOIR_SCORE_BILAN']);
  $html  = $affichage_direct ? '' : '<style>'.$_SESSION['CSS'].'</style>'.NL;
  $html .= $affichage_direct ? '' : '<h1>'.$bilan_intro.$bilan_titre_html.'</h1>'.NL;
  $html .= '<h2>'.html($matiere_et_groupe).'</h2>'.NL;
  if($texte_periode_html)
  {
    $html .= '<h2>'.$texte_periode_html.'</h2>'.NL;
  }
  // start CSV
  $csv = new CSV();
  $csv->add( 'Bilan '.$bilan_titre_pdf_csv_json , 1 )->add( 'Exploitation tableur' , 1 )->add( $matiere_et_groupe , 1 )->add( $texte_periode_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 = ( ( ($eleve_nb>$item_nb) && ($tableau_synthese_format=='eleve') ) || ( ($item_nb>$eleve_nb) && ($tableau_synthese_format=='item') ) ) ? 'portrait' : 'landscape' ;
  $pdf = new PDF_item_tableau_synthese( $make_officiel , 'A4' /*page_size*/ , $orientation_auto , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond , $legende );
  $pdf->initialiser( $eleve_nb , $item_nb , $tableau_synthese_format );
  $pdf->entete( 'Bilan '.$bilan_titre_pdf_csv_json , $matiere_et_groupe , $texte_periode_pdf_csv );
  // 1ère ligne
  $pdf->ligne_tete_cellule_debut();
  $th = ($tableau_synthese_format=='eleve') ? 'Élève' : 'Item' ;
  $html_table_head = '<thead><tr><th data-sorter="text">'.$th.'</th>';
  $csv->add( $th );
  if($tableau_synthese_format=='eleve')
  {
    foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
    {
      foreach($tab_item as $item_id=>$item_nom)
      {
        extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
        $pdf->ligne_tete_cellule_corps($item_abrev);
        $html_table_head .= '<th data-sorter="FromData" data-empty="bottom"'.infobulle($item_nom).'><dfn>'.html($item_abrev).'</dfn></th>';
        $csv->add( $item_abrev );
      }
    }
  }
  else
  {
    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 data-sorter="FromData" data-empty="bottom"><dfn>'.html($eleve_nom_prenom).'</dfn></th>';
      $csv->add( $eleve_nom_prenom );
    }
  }
  $pdf->ligne_tete_cellules_fin();
  $entete_vide   = ($repeter_entete)     ? '<th data-sorter="false" class="nu">&nbsp;</th>' : '' ;
  $checkbox_vide = ($affichage_checkbox) ? '<th data-sorter="false" class="nu">&nbsp;</th>' : '' ;
  $html_table_head .= '<th data-sorter="false" class="nu">&nbsp;</th><th data-sorter="FromData" data-empty="bottom">[ * ]</th><th data-sorter="FromData" data-empty="bottom">[ ** ]</th>'.$entete_vide.$checkbox_vide.'</tr></thead>'.NL;
  $csv->add( 'moy. scores '.$info_ponderation_courte )->add( '% items acquis' , 1 );
  // lignes suivantes
  $html_table_body = '';
  if($tableau_synthese_format=='eleve')
  {
    foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
    {
      extract($tab_eleve);  // $eleve_nom $eleve_prenom $eleve_id_gepi
      $eleve_nom_prenom = To::texte_eleve_identite($eleve_nom,$eleve_prenom,$eleves_ordre);
      $pdf->ligne_corps_cellule_debut( $eleve_nom_prenom );
      $entete = '<td>'.html($eleve_nom_prenom).'</td>';
      $html_table_body .= '<tr>'.$entete;
      $csv->add( $eleve_nom_prenom );
      foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
      {
        foreach($tab_item as $item_id=>$item_nom)
        {
          $score = isset($tab_score_eleve_item[$eleve_id][$matiere_id][$item_id]) ? $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id] : FALSE ;
          $pdf->afficher_score_bilan( $score , 0 /*br*/ );
          $checkbox_val = ($affichage_checkbox) ? $eleve_id.'x'.$item_id : '' ;
          $html_table_body .= Html::td_score($score,$tableau_tri_etat_mode,'',$checkbox_val);
          $csv->add( $score );
        }
      }
      if($matiere_nb>1)
      {
        $matiere_id = 0; // C’est l’indice choisi pour stocker les infos dans le cas d’une synthèse d’items issus de plusieurs matières
      }
      $valeur1 = (isset($tab_moyenne_scores_eleve[$matiere_id][$eleve_id])) ? $tab_moyenne_scores_eleve[$matiere_id][$eleve_id] : FALSE ;
      $valeur2 = (isset($tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id])) ? $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] : FALSE ;
      $pdf->ligne_corps_cellules_fin( $valeur1 , $valeur2 , FALSE , TRUE );
      $col_entete   = ($repeter_entete) ? $entete : '' ;
      $col_checkbox = ($affichage_checkbox) ? '<td class="nu"><input type="checkbox" name="id_user[]" value="'.$eleve_id.'"></td>' : '' ;
      $html_table_body .= '<td class="nu">&nbsp;</td>'.Html::td_score($valeur1,$tableau_tri_etat_mode,'%').Html::td_score($valeur2,$tableau_tri_etat_mode,'%').$col_entete.$col_checkbox.'</tr>'.NL;
      $csv->add( $valeur1 )->add( $valeur2 , 1 );
    }
  }
  else
  {
    foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
    {
      foreach($tab_item as $item_id=>$item_nom)
      {
        extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
        $pdf->ligne_corps_cellule_debut($item_abrev);
        $entete = '<td'.infobulle($item_nom).'>'.html($item_abrev).'</td>';
        $html_table_body .= '<tr>'.$entete;
        $csv->add( $item_abrev );
        foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
        {
          $score = isset($tab_score_eleve_item[$eleve_id][$matiere_id][$item_id]) ? $tab_score_eleve_item[$eleve_id][$matiere_id][$item_id] : FALSE ;
          $pdf->afficher_score_bilan( $score , 0 /*br*/ );
          $checkbox_val = ($affichage_checkbox) ? $eleve_id.'x'.$item_id : '' ;
          $html_table_body .= Html::td_score($score,$tableau_tri_etat_mode,'',$checkbox_val);
          $csv->add( $score );
        }
        $valeur1 = $tab_moyenne_scores_item[$item_id];
        $valeur2 = $tab_pourcentage_acquis_item[$item_id];
        $pdf->ligne_corps_cellules_fin( $valeur1 , $valeur2 , FALSE , TRUE );
        $col_entete   = ($repeter_entete) ? $entete : '' ;
        $col_checkbox = ($affichage_checkbox) ? '<td class="nu"><input type="checkbox" name="id_item[]" value="'.$item_id.'"></td>' : '' ;
        $html_table_body .= '<td class="nu">&nbsp;</td>'.Html::td_score($valeur1,$tableau_tri_etat_mode,'%').Html::td_score($valeur2,$tableau_tri_etat_mode,'%').$col_entete.$col_checkbox.'</tr>'.NL;
        $csv->add( $valeur1 )->add( $valeur2 , 1 );
      }
    }
  }
  $html_table_body = '<tbody>'.NL.$html_table_body.'</tbody>'.NL;
  $csv->add( NULL , 1 );
  // dernière ligne (doublée)
  $pdf->lignes_pied_cellules_debut( $info_ponderation_courte );
  $html_table_foot1 = '<tr><th>moy. scores '.$info_ponderation_courte.' [*]</th>';
  $html_table_foot2 = '<tr><th>% items acquis [**]</th>';
  $tab_CSV_foot1 = array('moy. scores '.$info_ponderation_courte);
  $tab_CSV_foot2 = array( '% items acquis');
  $row_entete   = ($repeter_entete)     ? '<tr><th class="nu">&nbsp;</th>' : '' ;
  $row_checkbox = ($affichage_checkbox) ? '<tr><th class="nu">&nbsp;</th>' : '' ;
  if($tableau_synthese_format=='eleve')
  {
    foreach($tab_matiere_item as $matiere_id=>$tab_item)  // Pour chaque item...
    {
      foreach($tab_item as $item_id=>$item_nom)
      {
        extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
        $valeur1 = $tab_moyenne_scores_item[$item_id];
        $valeur2 = $tab_pourcentage_acquis_item[$item_id];
        $pdf->ligne_corps_cellules_fin( $valeur1 , $valeur2 , TRUE , FALSE );
        $html_table_foot1 .= Html::td_score($valeur1,'score','%');
        $html_table_foot2 .= Html::td_score($valeur2,'score','%');
        $tab_CSV_foot1[] = $valeur1;
        $tab_CSV_foot2[] = $valeur2;
        $row_entete   .= ($repeter_entete) ? '<th'.infobulle($item_nom).'><dfn>'.html($item_abrev).'</dfn></th>' : '' ;
        $row_checkbox .= ($affichage_checkbox) ? '<td class="nu"><input type="checkbox" name="id_item[]" value="'.$item_id.'"></td>' : '' ;
      }
    }
  }
  else
  {
    foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
    {
      extract($tab_eleve);  // $eleve_nom $eleve_prenom $eleve_id_gepi
      $eleve_nom_prenom = To::texte_eleve_identite($eleve_nom,$eleve_prenom,$eleves_ordre);
      $valeur1 = (isset($tab_moyenne_scores_eleve[$matiere_id][$eleve_id])) ? $tab_moyenne_scores_eleve[$matiere_id][$eleve_id] : FALSE ;
      $valeur2 = (isset($tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id])) ? $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] : FALSE ;
      $pdf->ligne_corps_cellules_fin( $valeur1 , $valeur2 , TRUE , FALSE );
      $html_table_foot1 .= Html::td_score($valeur1,'score','%');
      $html_table_foot2 .= Html::td_score($valeur2,'score','%');
      $tab_CSV_foot1[] = $valeur1;
      $tab_CSV_foot2[] = $valeur2;
      $row_entete   .= ($repeter_entete) ? '<th><dfn>'.html($eleve_nom_prenom).'</dfn></th>' : '' ;
      $row_checkbox .= ($affichage_checkbox) ? '<td class="nu"><input type="checkbox" name="id_user[]" value="'.$eleve_id.'"></td>' : '' ;
    }
  }
  // les deux dernières cases (moyenne des moyennes)
  $colspan  = ($tableau_synthese_format=='eleve') ? $item_nb : $eleve_nb ;
  $pdf->ligne_corps_cellules_fin( $moyenne_moyenne_scores , $moyenne_pourcentage_acquis , TRUE , TRUE );
  $html_table_foot1 .= '<th class="nu">&nbsp;</th>'.Html::td_score($moyenne_moyenne_scores,'score','%').'<th class="nu">&nbsp;</th>'.$entete_vide.$checkbox_vide.'</tr>'.NL;
  $html_table_foot2 .= '<th class="nu">&nbsp;</th><th class="nu">&nbsp;</th>'.Html::td_score($moyenne_pourcentage_acquis,'score','%').$entete_vide.$checkbox_vide.'</tr>'.NL;
  $csv->add( $tab_CSV_foot1 )->add( $moyenne_moyenne_scores )->add( '' , 1 )
      ->add( $tab_CSV_foot2 )->add( '' )->add( $moyenne_pourcentage_acquis ,1 );
  $row_entete   .= ($repeter_entete)     ? '<th class="nu">&nbsp;</th><th class="nu">&nbsp;</th><th class="nu">&nbsp;</th>'.$entete_vide.$checkbox_vide.'</tr>'.NL : '' ;
  $row_checkbox .= ($affichage_checkbox) ? '<th class="nu">&nbsp;</th><th class="nu">&nbsp;</th><th class="nu">&nbsp;</th>'.$entete_vide.$checkbox_vide.'</tr>'.NL : '' ;
  $html_table_foot = '<tfoot>'.NL.'<tr class="vide"><td class="nu"></td><td class="nu" colspan="'.$colspan.'">&nbsp;</td><td class="nu"></td><td class="nu" colspan="2"></td>'.$entete_vide.$checkbox_vide.'</tr>'.NL.$html_table_foot1.$html_table_foot2.$row_entete.$row_checkbox.'</tfoot>'.NL;
  // sortie HTML
  $html .= '<hr>'.NL.'<h2>Tableau de synthèse (selon l’objet et le mode de tri choisis)</h2>'.NL;
  $html .= ($affichage_checkbox) ? '<form id="form_synthese" action="#" method="post">'.NL : '' ;
  $html .= '<table id="table_s" class="bilan_synthese vsort">'.NL.$html_table_head.$html_table_foot.$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) ); }
  }
  $script = $affichage_direct ? '$("#table_s").tablesorter();' : 'function tri(){$("#table_s").tablesorter();}' ;
  $html .= ($affichage_checkbox) ? HtmlForm::afficher_synthese_exploitation('eleves + eleves-items + items').'</form>'.NL : '';
  $html .= '<script>'.$script.'</script>'.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 );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Elaboration du tableau d’items par évaluations sélectionnées
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if($type_tableau_eval)
{
  // start HTML
  $html  = '<style>'.$_SESSION['CSS'].'</style>'.NL;
  $html .= '<h1>'.$bilan_intro.$bilan_titre_html.'</h1>'.NL;
  $html .= '<h2>'.html($matiere_et_groupe).'</h2>'.NL;
  // start PDF
  // 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
  $devoir_nb = count($tab_devoir);
  $item_nb = count($tab_devoir_item,COUNT_RECURSIVE) - $devoir_nb ;
  $orientation_auto = ( 8 + 4 + $eleve_nb < 5 + ($devoir_nb/4) + $item_nb ) ? 'portrait' : 'landscape' ;
  $pdf = new PDF_item_tableau_eval( $make_officiel , 'A4' /*page_size*/ , $orientation_auto , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond , $legende );
  $pdf->initialiser( $eleve_nb , $devoir_nb , $item_nb );
  $pdf->entete( $bilan_intro.$bilan_titre_pdf_csv_json , $matiere_et_groupe );
  // ligne vierge
  $ligne_vide = '<tr class="vide"><th class="nu" colspan="2"></th><td class="nu" colspan="'.$eleve_nb.'"></td></tr>';
  // 1ère ligne
  $html_table_head = '<thead><tr><th>Devoir</th><th>Item</th>';
  $pdf->ligne_tete( 'devoir' , 'Devoir' );
  $pdf->ligne_tete( 'item' , 'Item' );
  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);
    $html_table_head .= '<th data-empty="bottom"><dfn>'.html($eleve_nom_prenom).'</dfn></th>';
    $pdf->ligne_tete( 'eleve' , $eleve_nom_prenom );
  }
  $html_table_head .= '</tr></thead>'.NL;
  $pdf->ligne_tete( 'fin' );
  // lignes suivantes
  $html_table_body = '';
  foreach($tab_devoir_item as $devoir_id=>$tab_item)  // Pour chaque item de chaque devoir...
  {
    $rowspan = count($tab_item);
    $html_table_body .= $ligne_vide;
    $html_table_body .= '<tr><td rowspan="'.$rowspan.'">'.html($tab_devoir[$devoir_id]).'</td>';
    $pdf->ligne_corps( 'devoir' , $tab_devoir[$devoir_id] , $rowspan );
    foreach($tab_item as $item_id => $item_nom)
    {
      extract($tab_item_infos[$item_id][0]);  // $item_ref $item_nom $item_coef $item_cart $item_s2016 $item_lien $calcul_methode $calcul_limite $calcul_retroactif ($item_abrev)
      if($rowspan)
      {
        $rowspan = NULL;
      }
      else
      {
        $html_table_body .= '<tr>';
      }
      $html_table_body .= '<td'.infobulle($item_nom).'>'.html($item_abrev).'</td>';
      $pdf->ligne_corps( 'item' , $item_abrev );
      foreach($tab_eleve_infos as $eleve_id => $tab_eleve)  // Pour chaque élève...
      {
        if(isset($tab_eval[$eleve_id][$devoir_id][$item_id]))
        {
          extract($tab_eval[$eleve_id][$devoir_id][$item_id]);  // $note $date $info
          $html_table_body .= '<td>'.Html::note_image($note,$date,$info,TRUE,FALSE).'</td>';
          $pdf->ligne_corps( 'note' , $note );
        }
        else
        {
          $html_table_body .= '<td>&nbsp;</td>';
          $pdf->ligne_corps( 'note' , '' );
        }
      }
      $pdf->ligne_corps( 'fin' );
      $html_table_body .= '</tr>'.NL;
    }
  }
  $html_table_body = '<tbody>'.NL.$html_table_body.'</tbody>'.NL;
  // assemblage HTML
  $html .= '<table id="table_s" class="bilan_synthese">'.NL.$html_table_head.$html_table_body.'</table>'.NL;
  $html .= '<style>thead th{text-align:center;vertical-align:bottom} tr.vide{font-size:20%}</style>'.NL;
  // Légende
  if($legende=='oui')
  {
    $html .= Html::legende( array('codes_notation'=>TRUE) );
    $pdf->legende();
  }
  // On enregistre les sorties HTML et PDF
  FileSystem::ecrire_fichier(   CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','tableau',$fichier_nom).'.html' , $html );
  FileSystem::ecrire_objet_pdf( CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','tableau',$fichier_nom).'.pdf'  , $pdf );
}

// ////////////////////////////////////////////////////////////////////////////////////////////////////
// Elaboration du bulletin (moyenne et/ou appréciation) en HTML et PDF + CSV pour GEPI + CSV pour Pronote + Formulaire pour report prof
// ////////////////////////////////////////////////////////////////////////////////////////////////////

if( $type_bulletin && $make_html )
{
  $tab_bulletin_input = array();
  $bulletin_form = $bulletin_periode = $bulletin_alerte = '' ;
  if($_SESSION['USER_PROFIL_TYPE']=='professeur')
  {
    if(!empty($classe_id))
    {
      // code inclus par ./_inc/code_officiel_***.php : on a un identifiant de classe
      $CONFIGURATION_BULLETIN_REF = DB_STRUCTURE_OFFICIEL_CONFIG::DB_recuperer_classe_config_ref( $classe_id , 'bulletin' /*bilan_type*/ );
    }
    else
    {
      // code inclus par ./pages/releve_items.ajax.php : on a un identifiant de groupe qui peut être celui d’une classe
      $CONFIGURATION_BULLETIN_REF = DB_STRUCTURE_OFFICIEL_CONFIG::DB_recuperer_classe_config_ref( $groupe_id , 'bulletin' /*bilan_type*/ );
      if(empty($CONFIGURATION_BULLETIN_REF))
      {
        // finalement c’est vraiment un groupe (éventuellement de besoin), qui peut contenir des élèves issus de plusieurs classes...
        // faute de mieux on prend la configuration par défaut...
        $CONFIGURATION_BULLETIN_REF = 'defaut';
      }
    }
    $tab_configuration = DB_STRUCTURE_OFFICIEL_CONFIG::DB_recuperer_configuration( 'bulletin' /*bilan_type*/ , $CONFIGURATION_BULLETIN_REF );
    if(empty($tab_configuration))
    {
      Json::end( FALSE , 'Configuration bulletin / '.$CONFIGURATION_BULLETIN_REF.' non récupérée !' );
    }
    if($tab_configuration['moyenne_scores'])
    {
      // Attention : $groupe_id peut être un identifiant de groupe et non de classe, auquel cas les élèves peuvent être issus de différentes classes dont les états des bulletins sont différents...
      $DB_TAB = DB_STRUCTURE_BILAN::DB_lister_periodes_bulletins_saisies_ouvertes($liste_eleve);
      $nb_periodes_ouvertes = !empty($DB_TAB) ? count($DB_TAB) : 0 ;
      if($nb_periodes_ouvertes==1)
      {
        $bulletin_periode = '['.html($DB_TAB[0]['periode_nom']).']<input type="hidden" id="f_periode_eleves" name="f_periode_eleves" value="'.$DB_TAB[0]['periode_id'].'_'.$DB_TAB[0]['eleves_listing'].'">' ;
      }
      elseif($nb_periodes_ouvertes>1)
      {
        
        foreach($DB_TAB as $DB_ROW)
        {
          $selected = ($DB_ROW['periode_id']==$periode_id) ? ' selected' : '' ;
          $bulletin_periode .= '<option value="'.$DB_ROW['periode_id'].'_'.$DB_ROW['eleves_listing'].'"'.$selected.'>'.html($DB_ROW['periode_nom']).'</option>';
        }
        $bulletin_periode = '<select id="f_periode_eleves" name="f_periode_eleves">'.$bulletin_periode.'</select>';
      }
      else
      {
        $bulletin_form = '<li>Report forcé vers un bulletin sans objet : pas de bulletin scolaire ouvert pour ce regroupement.</li>';
      }
    }
    else
    {
      $bulletin_form = '<li>Report forcé vers un bulletin sans objet : les bulletins scolaires sont configurés sans moyenne.</li>';
    }
  }
  $bulletin_body = '';
  $pdf = new PDF_item_bulletin( $make_officiel , 'A4' /*page_size*/ , $orientation , $marge_gauche , $marge_droite , $marge_haut , $marge_bas , $couleur , $fond );
  $pdf->initialiser_et_entete( $bilan_titre_pdf_csv_json , $eleve_nb , $matiere_et_groupe , $texte_periode_pdf_csv , $info_ponderation_complete );
  $csv = new CSV();
  $csv_pronote  = new CSV();
  $csv->add( 'Bilan '.$bilan_titre_pdf_csv_json , 1 )->add( $texte_periode_pdf_csv , 1 )->add( 'Moyennes sur 20 ou 100.' , 2 )
      ->add( array('MATIERE / GROUPE' , 'NOM' , 'PRENOM' , 'NOTE / 20' , 'NOTE / 100') , 1 );
  $csv_pronote->add( array('NOM' , 'PRENOM' , 'NOTE' , 'APPRECIATION') , 1 );
  $tab_csv_gepi = array_fill_keys( array('note_appreciation','note','appreciation_pourcent_acquis','appreciation_moyennes_scores') , NULL );
  foreach($tab_csv_gepi as $gepi_type_donnees => $null)
  {
    $tab_csv_gepi[$gepi_type_donnees] = new CSV();
    $tab_csv_gepi[$gepi_type_donnees]->add( array('GEPI_IDENTIFIANT' , 'NOTE' , 'APPRECIATION') , 1 ); // Ajout du préfixe 'GEPI_' pour éviter un bug avec M$ Excel « SYLK : Format de fichier non valide » (http://support.microsoft.com/kb/323626/fr)
    $csv_pronote  = new CSV();
  }
  // Pour chaque élève...
  foreach($tab_eleve_infos as $eleve_id => $tab_eleve)
  {
    extract($tab_eleve);  // $eleve_INE $eleve_nom $eleve_prenom $eleve_id_gepi
    $eleve_nom_prenom = To::texte_eleve_identite($eleve_nom,$eleve_prenom,$eleves_ordre);
    // Si cet élève a été évalué...
    if(isset($tab_eval[$eleve_id]))
    {
      $note                         = ($tab_moyenne_scores_eleve[$matiere_id][$eleve_id]     !== FALSE) ? sprintf("%04.1f",$tab_moyenne_scores_eleve[$matiere_id][$eleve_id]/5)                                                           : '-' ;
      $appreciation_pourcent_acquis = ($tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id] !== FALSE) ? $tab_pourcentage_acquis_eleve[$matiere_id][$eleve_id].'% d’items acquis ('.$tab_infos_acquis_eleve[$matiere_id][$eleve_id].')' : '-' ;
      $appreciation_moyennes_scores = ($tab_moyenne_scores_eleve[$matiere_id][$eleve_id]     !== FALSE) ? ( ($conversion_sur_20) ? 'Moyenne des scores : '.$tab_moyenne_scores_eleve[$matiere_id][$eleve_id].'%'.' soit '.str_replace('.',',',sprintf("%04.1f",$tab_moyenne_scores_eleve[$matiere_id][$eleve_id]/5)).'/20.' : 'Moyenne des scores de '.$tab_moyenne_scores_eleve[$matiere_id][$eleve_id].'%.' ) : '-' ;
      $bulletin_body  .= '<tr><th>'.html($eleve_nom_prenom).'</th><td class="hc">'.$note.'</td><td class="hc">'.$appreciation_pourcent_acquis.'</td></tr>'.NL;
      $pdf->ligne_eleve( $eleve_nom_prenom , $note , $appreciation_pourcent_acquis );
      $pourcentage = ($note!=='-') ? $tab_moyenne_scores_eleve[$matiere_id][$eleve_id] : '-' ;
      $note        = !is_null($note) ? str_replace('.',',',$note) : $note ; // Pour GEPI et PRONOTE je remplace le point décimal par une virgule sinon le tableur convertit en date...
      $csv->add( array( $matiere_et_groupe , $eleve_nom , $eleve_prenom , $note , $pourcentage ) , 1 );
      $csv_pronote->add( array( $eleve_nom , $eleve_prenom , $note , $appreciation_pourcent_acquis ) , 1 );
      $tab_csv_gepi['note_appreciation']           ->add( array( $eleve_id_gepi , $note , $appreciation_pourcent_acquis ) , 1 );
      $tab_csv_gepi['note']                        ->add( array( $eleve_id_gepi , $note , ''                            ) , 1 );
      $tab_csv_gepi['appreciation_pourcent_acquis']->add( array( $eleve_id_gepi , ''    , $appreciation_pourcent_acquis ) , 1 );
      $tab_csv_gepi['appreciation_moyennes_scores']->add( array( $eleve_id_gepi , ''    , $appreciation_moyennes_scores ) , 1 );
      if( ($bulletin_periode) && ($tab_moyenne_scores_eleve[$matiere_id][$eleve_id] !== FALSE) )
      {
        $tab_bulletin_input[] = $eleve_id.'_'.($tab_moyenne_scores_eleve[$matiere_id][$eleve_id]/5);
      }
    }
  }
  if($bulletin_periode)
  {
    if(count($tab_bulletin_input))
    {
      if($releve_modele=='matiere')
      {
        $bulletin_matiere = '['.html($matiere_nom).']<input type="hidden" id="f_rubrique" name="f_rubrique" value="'.$matiere_id.'">';
      }
      else
      {
        $bulletin_matiere = HtmlForm::afficher_select(DB_STRUCTURE_COMMUN::DB_OPT_matieres_professeur($_SESSION['USER_ID']) , 'f_rubrique' /*select_nom*/ , FALSE /*option_first*/ , FALSE /*selection*/ , '' /*optgroup*/ );
      }
      $bulletin_form = '<li><form id="form_report_bulletin"><fieldset><button id="bouton_report" type="button" class="eclair">Report forcé</button> vers le bulletin <em>SACoche</em> '.$bulletin_periode.'<input type="hidden" id="f_eleves_moyennes" name="f_eleves_moyennes" value="'.implode('x',$tab_bulletin_input).'"> '.$bulletin_matiere.'</fieldset></form><label id="ajax_msg_report"></label></li>';
      $bulletin_alerte = '<div class="danger">Un report forcé interrompt le report automatique des moyennes pour le bulletin et la matière concernée.</div>' ;
    }
    else
    {
      $bulletin_form = '<li>Report forcé vers un bulletin sans objet : aucune moyenne chiffrée n’a pu être produite.</li>';
    }
  }
  $pdf->derniere_ligne( $info_ponderation_complete , $moyenne_scores_affichee , $moyenne_pourcentage_acquis );
  $bulletin_head  = '<thead><tr><th>Élève</th><th>Moyenne '.$info_ponderation_complete.' sur 20<br>(des scores d’acquisitions)</th><th>Élément d’appréciation<br>(pourcentage d’items acquis)</th></tr></thead>'.NL;
  $bulletin_body  = '<tbody>'.NL.$bulletin_body.'</tbody>'.NL;
  $bulletin_foot  = '<tfoot><tr><th>Moyenne '.$info_ponderation_complete.' sur 20</th><th class="hc">'.$moyenne_scores_affichee.'</th><th class="hc">'.$moyenne_pourcentage_acquis.'% d’items acquis</th></tr></tfoot>'.NL;
  $html  = '<h1'.$bilan_intro.$bilan_titre_html.'</h1>';
  $html .= '<h2>'.html($matiere_et_groupe).'</h2>';
  $html .= '<h2>'.$texte_periode_html.'</h2>';
  $html .= '<h2>Moyenne sur 20 / Élément d’appréciation</h2>';
  $html .= '<table id="export20" class="hsort">'.NL.$bulletin_head.$bulletin_foot.$bulletin_body.'</table>'.NL;
  $html .= '<script>$("#export20").tablesorter({ headers:{2:{sorter:false}} });</script>'.NL;
  // On enregistre les sorties HTML / PDF / CSV
  FileSystem::ecrire_fichier(  CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','bulletin',$fichier_nom).'.html',$html);
  FileSystem::ecrire_objet_pdf(CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','bulletin',$fichier_nom).'.pdf' ,$pdf );
  FileSystem::ecrire_objet_csv(CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','bulletin',$fichier_nom).'.csv' ,$csv);
  FileSystem::ecrire_objet_csv(CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','pronote' ,$fichier_nom).'.csv' ,$csv_pronote,'Pronote');
  foreach($tab_csv_gepi as $gepi_type_donnees => $csv_gepi)
  {
    FileSystem::ecrire_objet_csv(CHEMIN_DOSSIER_EXPORT.str_replace('<REPLACE>','bulletin_'.$gepi_type_donnees,$fichier_nom).'.csv',$csv_gepi,'GEPI');
  }
}

?>