<?php
/**
 * Ce script permet de déclarer la classe or_aff.
 *
 * @package openresultat
 * @version SVN : $Id$
 */

/**
 * Inclusion d'une librairie permettant de gérer les problématiques d'encodage.
 * Les fichiers générés depuis la version 1.00 de l'applicatif peuvent avoir
 * été généré dans divers encodage. Cette librairie permet de palier à cette
 * problématique en passant les contenus de fichiers générés par cette
 * librairie.
 */
require "encoding.class.php";

/**
 * Class or_aff
 */
class or_aff {

    /**
     * Identifiant de l'élection si une élection est sélectionnée
     * @var integer
     */
    protected $election = NULL;

    /**
     * Tableau contenant les paramètres de l'élections
     * @var array
     */
    protected $params = array();

    /**
     * Tableau contenant les paramètres de chaque blocs
     * de l'animation
     * @var array
     */
    protected $params_blocs = array();

    /**
     * @var jscript
     */
    protected $jscript = "";

    /**
     * @var array
     */
    protected $colors = array();

    /**
     * Constructeur
     *
     * @param $election id de l'élection
     * @param $identifier
     */
    function __construct($election = NULL, $identifier = NULL) {
        //
        if ($election == NULL || !is_dir(AFF_RESULTS_PATH.$election)) {
            die("Cette élection n'existe pas.");
        }
        //
        $this->election = $election;
        //
        define("AFF_ELECTION_RESULTS_PATH", AFF_RESULTS_PATH.$election."/");
        define("AFF_ELECTION_RESULTS_URL", AFF_RESULTS_URL.$election."/");
        //
        $this->identifier = $identifier;
        //
        $this->set_params();
        if (empty($this->get_params())) {
            return;
        }
        
        if ($this->set_param_blocs() === false) {
            echo 'Le paramétrage des blocs est erroné';
            return;
        }
        $this->set_unites_infos();
        $this->set_infos_candidats();
        $this->set_resultats_unites();
        $this->set_participation_unites();
        $this->set_perimetres();
        $this->set_repartition_sieges();
        //
        $this->initialize_animation_routine();
        //
        $this->display_html_header();
        //
        $this->display();
    }

    /**
     * Affichage de la page
     * @return void
     */
    protected function display() {
        //Récupère les informations nécessaires pour l'affichage
        $params = $this->get_params();
        $params_entete = $params['entete'];

        //Si un logo a été fourni son emplacement est stocké dans les paramètres
        //Le html de l'image est donc écris en utilisant le template de l'image
        //et en donnant pour attribut 'src' le chemin vers l'image
        $html_logo = '';
        if (! empty($params['logo'])) {
            $html_logo = sprintf(
                '<img class="logo" src="%s" alt="logo" style="float:left;width:50;height:50px;">',
                $params['logo']
            );
        }

        //L'extrapolation des variables se fait en trois temps :
        //  1- coupe la chaîne de caractères en "mots" en coupant selon les ' '.
        //     Les mots sont stockées dans un tableau.
        //  2- test pour chaque mots si il correspond à un mot clé. Si c'est le cas
        //     effectue le traitement nécessaire et remplace la valeur obtenu dans
        //     la case du tableau correpsondant au mot.
        //     Ex : $mots[1] = 'nb_unite'  => 'nb_unite' vaut 5 par exemple => $mots[1] = 5
        //  3- reconstitue la chaîne de caractère avec le tableau des mots en mettant un ' '
        //     entre chaque mots
        $motsEntetes = explode(' ', $params_entete['sous_titre']);
        $sousTitre = '';
        foreach ($motsEntetes as $key => $mot) {
            switch ($mot) {
                case 'nb_unite':
                    $listeUnite = $this->get_unites_by_type(
                        $params['unites']['perimetre'],
                        $params['unites']['type']
                    );
                    $motsEntetes[$key] = count($listeUnite);
                    break;
                case 'nb_unite_total':
                    $unitesInfos = $this->get_unites_infos();
                    $motsEntetes[$key] = count($unitesInfos);
                    break;
                case 'nb_unite_arrivees':
                    $listeUniteArrivees = $this->get_liste_unite_defile();
                    $motsEntetes[$key] = count($listeUniteArrivees);
                    break;
                case 'nb_unite_total_arrivees':
                    $unitesInfos = $this->get_unites_infos();
                    $nbUnitesTotalArrivees = 0;
                    foreach ($unitesInfos as $unite) {
                        if ($unite['envoie'] === true) {
                            $nbUnitesTotalArrivees++;
                        }
                    }
                    $motsEntetes[$key] = $nbUnitesTotalArrivees;
                    break;
                default:
                    break;
            }
        }
        $sousTitre = implode(' ', $motsEntetes);
        
        //Code html de l'entete de la page. Les éléments paramétrés sont dans l'ordre :
        //  - la couleur du bandeau de titre (bandeau + bordure)
        //  - le code html permettant d'afficher le logo
        //  - la couleur du titre
        //  - le titre
        //  - la couleur du sous-titre
        //  - le sous-titre
        $html_entete = sprintf(
            "
            <div class='navbar navbar-inverse navbar-fixed-top' role='navigation' style='background-color:%s;border-color:%s;'>
                %s
                <div class='container-fluid'>
                    <div class='navbar-header'>
                        <span class='navbar-brand' style='color:%s;'> &nbsp; %s</span>
                    </div>
                    <ul class=\"nav navbar-nav navbar-right\">
                        <li><span style='color:%s;'>%s</span></li>
                    </ul>
                </div>
            </div>",
            $params_entete['couleur_bandeau'],
            $params_entete['couleur_bandeau'],
            $html_logo,
            $params_entete['couleur_titre'],
            $params_entete['titre'],
            $params_entete['couleur_titre'],
            $sousTitre
        );
        echo $html_entete;

        // Code html du contenu de la page c'est à dire des blocs et de
        //la sidebar. L'affichage de la sidebar depend de sa position,
        //le code html de la sidebar est donc récupéré à part.
        //La sidebar n'est affiché que si elle est paramétrée dans le tableau
        //c'est à dire que si la clé 'sidebar' existe
        $blocs = $this->get_params_blocs();
        if (is_array($blocs)) {
            $html_contenu = '<br><div class="container-responsive">';
            $html_blocs = '';
    
            //Pour chaque bloc, récupération de son code html et ajout
            //au code html du contenu de la page
            foreach ($blocs as $nom => $bloc) {
                if ($nom !== 'sidebar' && array_key_exists('type', $bloc) && $bloc['type'] != '') {
                    $nomFonction = 'get_html_'.$bloc['type'];
                    if (method_exists($this, $nomFonction)) {
                        $html_bloc = $this->$nomFonction($bloc);
                        //Gestion de l'offset
                        $html_offset = '';
                        if (array_key_exists('offset', $bloc) &&
                            is_numeric($bloc['offset'])
                            && $bloc['offset'] > 0) {
                            $html_offset = 'col-sm-offset-'.$bloc['offset'];
                        }
                        //Ajout du bloc au code html de tous les blocs
                        $html_blocs .= sprintf(
                            '<div class="col-sm-%d %s">
                                %s
                            </div>',
                            $bloc['taille'],
                            $html_offset,
                            $html_bloc
                        );
                    }
                }
            }
    
            // Trois cas à gérer :
            // 1- La sidebar existe et est positionnée à gauche :
            //    -> Récupère le code html de la sidebar et on insère ce code
            //       dans celui du contenu de la page, avant celui des blocs
            // 2- La sidebar existe et est positionnée à droite :
            //    -> Récupère le code html de la sidebar et on insère ce code
            //       dans celui du contenu de la page, après celui des blocs
            // 3- Il n'y a pas de sidebar :
            //    -> Le contenu de la page ne contiens que le code html des
            //       blocs
            if (array_key_exists('sidebar', $blocs)) {
                $html_sidebar = $this->get_html_liste_unite($blocs['sidebar']);
                if ($blocs['sidebar']['position'] === 'gauche') {
                    $html_contenu .= sprintf(
                        '<div class="col-sm-%d sidebar-left">
                            %s
                        </div>
                            %s
                        </div>',
                        $blocs['sidebar']['taille'],
                        $html_sidebar,
                        $html_blocs
                    );
                } else {
                    $html_contenu .= sprintf(
                        '%s
                        <div class="col-sm-%d sidebar">
                            %s
                        </div>
                        </div>',
                        $html_blocs,
                        $blocs['sidebar']['taille'],
                        $html_sidebar
                    );
                }
            } else {
                $html_contenu .= $html_blocs.'</div>';
            }
    
            echo $html_contenu;
        }
    }

    /**
     * template d'affichage des images pour les candidats
     *
     * @var string
     */
    protected $template_image = '<img class="img-responsive" src="%s" alt="logo">';

    /**
     * Initialise la routine d'animation
     * @return void
     */
    protected function initialize_animation_routine() {
        //
        //include("../dyn/session.inc");
        session_name('openresultat');
        session_start();

        // La liste des unités à faire défilées est différentes si les unités
        // de la sidebar sont cliquable ou pas. Si c'est le cas toutes les unités
        // doivent défiler, sinon seules celles qui ont été envoyées défile
        $params_blocs = $this->get_params_blocs();
        $params = $this->get_params();
        // Par défaut seule les unités cliquable défile, cependant si les unités
        // sont définies comme cliquable dans le paramétrage, toutes les unités
        // de la liste défile
        $liste_entite = $this->get_liste_unite_defile();
        if (is_array($params_blocs) &&
            array_key_exists('sidebar', $params_blocs) &&
            array_key_exists('cliquable', $params_blocs['sidebar']) &&
            $params_blocs['sidebar']['cliquable'] === 'oui') {
                $unites = $params['unites'];
                $liste_entite = $this->get_unites_by_type($unites['perimetre'], $unites['type']);
        }
        // Initialisation de la variable click pour la fonctionnalité unite arrive clickable
        if (!isset($_SESSION['click'])) {
            //
            $_SESSION['click'] = 0;
        }

        //
        if (!isset($_SESSION['b'])) {
            //
            $_SESSION['b'] = 0;
        }

        // unite arrivé clickable
        if (isset($_GET['click']) and isset($_GET['b']) and $_GET['click'] != $_SESSION['click']) {
            //
            $_SESSION['click'] += 1;
            $_SESSION['b'] = $_GET['b'];
            return;
        }

        // Si la valeur de la session n'existe pas dans la liste des unites
        if (!in_array($_SESSION['b'], $liste_entite)) {
            // On affecte la première valeur du tableau
            $_SESSION['b'] = reset($liste_entite);
            return;
        }
        //
        $test = 0;
        while ($test == 0) {
            if ($_SESSION['b'] == current($liste_entite)) {
                $_SESSION['b'] = next($liste_entite);
                if ($_SESSION['b'] == false)
                    $_SESSION['b'] = reset($liste_entite);
                $test = 1;
            }
            next($liste_entite);
        }
    }

    /**
     * Affichage du header html
     * @return void
     */
    protected function display_html_header() {
        // Le thème par défaut est t01
        $theme = 't01';
        if (isset($_GET['theme']) && $_GET['theme'] !== null && $_GET['theme'] !== '') {
            $theme = $_GET['theme'];
        }
        $params = $this->get_params();
        printf(
            $this->template_html_header,
            $params['animation']["refresh"],
            $theme,
            $params['animation']['feuille_style']
        );
    }

    /**
     * Affichage du footer html
     * @return void
     */
    protected function display_html_footer() {
        // Le thème par défaut est t01
        $theme = 't01';
        if (isset($_GET['theme']) && $_GET['theme'] !== null && $_GET['theme'] !== '') {
            $theme = $_GET['theme'];
        }

        printf(
            $this->template_html_footer,
            $theme,
            $this->get_jscript()
        );
    }

    /**
     * Supprime l'affichage
     * @return void
     */
    function __destruct() {
        //
        $this->display_html_footer();
    }

    /**
     * RESULTATS / PERIMETRE
     * Renvoie le code html du bloc d'affichage des résultats du périmètre
     * choisit en paramétre
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string code html
     */
    protected function get_html_resultat_global($parametres) {
        //Récupération des données nécessaires à l'affichages
        $param = $this->get_params();
        //Récupération des résultats du périmètre calculé à partir des unités envoyées
        $resultats_perimetre = $this->calcul_resultats_unites_arrivees();
        //Récupération du nombre d'inscrits global (pour toutes les unités quels que soit leur état)
        $resultatsGlobal = $this->get_resultats_unite($param['unites']['perimetre']);
        $totalInscrits = isset($resultatsGlobal['inscrit']) ?
            $resultatsGlobal['inscrit']: 0;
        //Vérification que les données voulues existent
        if (empty($resultats_perimetre)) {
            return;
        }
        $donneesAAfficher = array();

        //Calcul du pourcetage de votant
        $pourcentageVotants = '0,00%';
        $inscritsunitesarrives = '';
        if (array_key_exists('inscrit', $resultats_perimetre)
            && ! empty($resultats_perimetre['inscrit'])) {
            $inscritsunitesarrives = $resultats_perimetre['inscrit'];
            $pourcentageVotants = str_replace(
                ".",
                ",",
                number_format(round($resultats_perimetre["votant"] * 100 / $inscritsunitesarrives, 2),2)
            );
        }
        //Code html du tableau des résultats des candidats
        $resultats_table_body_content = "";

        if (array_key_exists('candidats', $resultats_perimetre) &&
        ! empty($resultats_perimetre['candidats'])
        ) {
            // Tri par numéro d'ordre des candidats
            ksort($resultats_perimetre['candidats']);
            foreach ($resultats_perimetre['candidats'] as $ordre => $candidat) {
                $infoCandidat = $this->get_infos_candidat($ordre);
                $badge = sprintf(
                    '<span class="badge color-chart" style="background-color:%s;">&nbsp;</span>',
                    $infoCandidat['couleur']
                );
    
                //Code html de la photo du candidat, seulement si les photos sont paramétrées
                //pour l'affichage du bloc et si une photo existe pour le candidat
                $html_photo = '';
                if (array_key_exists('photo', $parametres) &&
                    ! empty($infoCandidat['photo']) &&
                    $parametres['photo'] == 'oui'
                ) {
                    $html_photo = sprintf(
                        $this->template_image,
                        $infoCandidat['photo']
                    );
                }
    
                //Remplissage d'une ligne du tableau des résultats, de cette facon  :
                //          candidat           |                tx
                //  photo + badge + nom prenom | tx de vote exprime en faveur du candidat
                //
                $resultats_table_body_content .= sprintf(
                    $this->template_resultats_ligne,
                    $html_photo,
                    $badge." ".Encoding::toUTF8($infoCandidat['libelle']),
                    $candidat['voix'],
                    str_replace(".", ",", number_format(floatval($candidat['tx']), 2))."%"
                );
    
                //Récupération des données qui permette de réaliser le graphique
                $donneesAAfficher[$infoCandidat['libelle']] = array(
                    'valeur' => $candidat['voix'],
                    'couleur' => $infoCandidat['couleur']
                );
            }
        }
        //Code html du tableau des résultats dans lequel est inséré
        //le code html des lignes de résultats des candidats
        $html_tableau_resultats = sprintf(
            $this->template_resultats_table,
            $resultats_table_body_content
        );

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            $html_graph = $this->get_html_canvas($parametres, 'chartResultatPerimetre');
            $this->get_script_chart('chartResultatPerimetre', $donneesAAfficher, $parametres['diagramme']);
        }

        //Code html du blocs des résultats du périmètres
        $html_resultats_perimetre = sprintf(
            $this->template_resultats_perimetre,
            $parametres['panel'],
            count($resultats_perimetre),
            $totalInscrits,
            $resultats_perimetre['inscrit'],
            $resultats_perimetre['votant'],
            $pourcentageVotants,
            $resultats_perimetre['blanc'],
            $resultats_perimetre['nul'],
            $resultats_perimetre['exprime'],
            $html_tableau_resultats,
            $html_graph
        );
        return $html_resultats_perimetre;
    }

    /**
     * RESULTATS / ENTITE
     * Renvoie le code html du bloc d'affichage des résultats d'une unité
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string code html
     */
    protected function get_html_resultat_unite($parametres) {
        //Récupération de l'identifiant de l'unité
        $unite = $_SESSION['b'];
        $resultats = is_numeric($unite) ? $this->get_resultats_unite($unite) : null;
        if (empty($resultats)) {
            return;
        }

        //Calcul du pourcentage de votant
        $pourcentageVotants = '0,00%';
        $resultats['votant'] = isset($resultats['votant']) && is_numeric($resultats['votant']) ? $resultats['votant'] : 0;
        if (isset($resultats['inscrit'])
            && is_numeric($resultats['inscrit'])
            && $resultats['inscrit'] != 0) {
            $pourcentageVotants = str_replace('.', ',', number_format(round($resultats['votant'] * 100 / $resultats['inscrit'], 2),2));
        }

        //code html du tableau des résultats des candidats
        $resultats_table_body_content = "";
        $donneesAAfficher = array();

        // Tri par numéro d'ordre des candidats
        ksort($resultats['candidats']);
        foreach ($resultats['candidats'] as $ordre => $candidat) {
            $infoCandidat = $this->get_infos_candidat($ordre);
            $badge = sprintf(
                '<span class="badge color-chart" style="background-color:%s;">&nbsp;</span>',
                $infoCandidat['couleur']
            );
            $html_photo = '';
            if (array_key_exists('photo', $parametres) &&
                ! empty($candidat['photo']) &&
                $parametres['photo'] == 'oui'
            ) {
                $html_photo = sprintf(
                    $this->template_image,
                    $candidat['photo']
                );
            }

            // Permet d'afficher 0 si aucun résultat n'est enregistré pour le candidat
            $voix = array_key_exists('voix', $candidat) && ! empty($candidat['voix']) ?
                $candidat['voix'] :
                0;
            
            $resultats_table_body_content .= sprintf(
                $this->template_resultats_ligne,
                $html_photo,
                $badge." ".Encoding::toUTF8($infoCandidat['libelle']),
                $voix,
                str_replace(".", ",", number_format(floatval($candidat['tx']), 2))."%"
            );

            $donneesAAfficher[$infoCandidat['libelle']] = array(
                'valeur' => $candidat['voix'],
                'couleur' => $infoCandidat['couleur']
            );
        }

        $html_tableau_resultats = sprintf(
            $this->template_resultats_table,
            $resultats_table_body_content
        );

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) &&
            ! empty($parametres['diagramme']) &&
            ! empty($donneesAAfficher)
        ) {
            $html_graph = $this->get_html_canvas($parametres, 'chartResultatEntite');
            $this->get_script_chart('chartResultatEntite', $donneesAAfficher, $parametres['diagramme']);
        }

        //Code html du bloc d'affichage des résultats de l'entité
        $html_resultat_entite = sprintf(
            $this->template_resultats_entite,
            $parametres['panel'],
            count($resultats['candidats']),
            $resultats['libelle'],
            $resultats['inscrit'],
            $resultats['votant'],
            $pourcentageVotants,
            $resultats['blanc'],
            $resultats['nul'],
            $resultats['exprime'],
            $html_tableau_resultats,
            $html_graph
        );
        return $html_resultat_entite;
    }

    /**
     * PARTICIPATION / PERIMETRE
     * Renvoie le code html du bloc réalisant l'affichage de la participation
     * pour le périmètre d'affichage choisit en paramétre
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string code html
     */
    protected function get_html_participation_globale($parametres) {
        //Récupération des données nécessaires à l'affichage
        $params = $this->get_params();
        // L'affichage de la participation globale consiste à afficher la participation
        // du périmètres choisi
        $participation_perimetre = $this->get_participation_unite($params['unites']['perimetre']);
        $resultatPerimetre = $this->get_resultats_unite($params['unites']['perimetre']);
        $inscrits = isset($resultatPerimetre['inscrit']) ? $resultatPerimetre['inscrit'] : 0;
        //Vérification que les données existe si ce n'est pas le cas l'affichage
        //n'est pas réalisé
        if (empty($participation_perimetre)) {
            return;
        }

        $html_lignes_participation = "";
        //code html du tableau de la participation. Il y a une ligne pour chaque tranche horaire
        $totalVotants = 0;
        $fermeture = '00:00:00';
        foreach ($participation_perimetre['participations'] as $tranche => $participation) {
            // Récupération du code html de la ligne du tableau correspondant à l'unité
            // et calcul du total de votant
            $votants = 0;
            if (array_key_exists('votant', $participation) && ! empty($participation['votant'])) {
                $votants = $participation['votant'];
                // Récupération de l'heure de fermeture pour connaitre le total de la participation
                // car la participation est cumulative
                if ($tranche > $fermeture) {
                    $fermeture = $tranche;
                }
            }

            $html_lignes_participation .= sprintf(
                $this->template_participation_ligne,
                $tranche,
                $votants,
                str_replace(".", ",", number_format(floatval($participation['tx']), 2))."%"
            );
        }
        $html_tableau_participation = sprintf(
            $this->template_participation_table,
            $html_lignes_participation
        );

        //Code html de la zone de dessin du graphique et récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            // Récupération des valeurs permettant de créer le diagramme
            // Permet d'éviter d'avoir un résultats négatif à afficher dans le diagramme
            $totalVotants = $participation_perimetre['participations'][$fermeture]['votant'];
            $nonVotants = ($inscrits > $totalVotants) ? $inscrits - $totalVotants : 0;
            
            // Récupération des couleurs du diagramme
            $couleurAbst =array_key_exists('couleur_abstention', $parametres)
                    && ! empty($parametres['couleur_abstention']) ?
                $parametres['couleur_abstention'] :
                '#dddddd';

            $couleurVotants=array_key_exists('couleur_participation', $parametres)
                && ! empty($parametres['couleur_participation']) ?
                $parametres['couleur_participation'] :
                '#0000ff';

            $donneesAAfficher = array(
                'votants' => array(
                    'valeur' => $totalVotants,
                    'couleur' => $couleurVotants
                ),
                'non votants' => array(
                    'valeur' => $nonVotants,
                    'couleur' => $couleurAbst
                ),
            );

            // Récupération du script du diagramme
            $html_graph = $this->get_html_canvas($parametres, 'chartParticipationPerimetre');
            $this->get_script_chart('chartParticipationPerimetre', $donneesAAfficher, $parametres['diagramme']);
        }

        //code html du bloc d'affichage de la participation
        $html_participation_perimetre = sprintf(
            $this->template_participation_perimetre,
            $parametres['panel'],
            $inscrits,
            $html_tableau_participation,
            $html_graph
        );

        return $html_participation_perimetre;
    }

    /**
     * PARTICIPATION / ENTITE (unite)
     * Renvoie le code html du bloc d'affichage de la participation d'une
     * unité
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string code html
     */
    protected function get_html_participation_unite($parametres) {
        //Récupération de l'identifiant de l'unité
        $params=$this->get_params();
        // Unité en cours d'affichage
        $unite = $_SESSION['b'];
        if (empty($unite)) {
            return;
        }
        $entite_infos = $this->get_participation_unite($unite);
        if (empty($entite_infos)) {
            return;
        }

        //Code html du tableau contenant la participation pour chaque tranche horaire
        $html_lignes_participation = '';
        $totalVotants = 0;
        $fermeture = '00:00:00';
        foreach ($entite_infos["participations"] as $tranche => $participation) {
            // Récupération du code html de la ligne du tableau correspondant à l'unité et
            // calcul du total de votant
            $votants = 0;
            if (array_key_exists('votant', $participation) && ! empty($participation['votant'])) {
                $votants = $participation['votant'];
                // Récupération de l'heure de fermeture pour connaitre le total de la participation
                // car la participation est cumulative
                if ($tranche > $fermeture) {
                    $fermeture = $tranche;
                }
            }

            $html_lignes_participation .= sprintf(
                $this->template_participation_ligne,
                $tranche,
                $votants,
                str_replace(".", ",", number_format(floatval($participation['tx']),2))."%"
            );
        }

        $html_tableau_participation = sprintf(
            $this->template_participation_table,
            $html_lignes_participation
        );

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            // Récupération des valeurs permettant de créer le diagramme
            // Permet d'éviter d'avoir un résultats négatif à afficher dans le diagramme
            $inscrits = array_key_exists('inscrit', $entite_infos) && ! empty($entite_infos['inscrit']) ?
                $entite_infos['inscrit'] : 0;
            // Récupération des valeurs permettant de créer le diagramme
            // Total votant = nombre de votant saisie sur la dernière tranche horaire (participation cumulative)
            $totalVotants = 0;
            if (array_key_exists($fermeture, $entite_infos['participations'])) {
                $totalVotants = $entite_infos['participations'][$fermeture]['votant'];
            }
            $nonVotants = ($inscrits > $totalVotants) ? $inscrits - $totalVotants : 0;

            // Récupération des couleurs du diagramme
            $couleurAbst =array_key_exists('couleur_abstention', $parametres)
                    && ! empty($parametres['couleur_abstention']) ?
                $parametres['couleur_abstention'] :
                '#dddddd';

            $couleurVotants =array_key_exists('couleur_participation', $parametres)
                && ! empty($parametres['couleur_participation']) ?
                $parametres['couleur_participation'] :
                '#0000ff';
    
            $donneesAAfficher = array(
                'votants' => array(
                    'valeur' => $totalVotants,
                    'couleur' => $couleurVotants
                ),
                'non votants' => array(
                    'valeur' => $nonVotants,
                    'couleur' => $couleurAbst
                ),
            );

            // Récupération du diagramme
            $html_graph = $this->get_html_canvas($parametres, 'chartParticipationEntite');
            $this->get_script_chart('chartParticipationEntite', $donneesAAfficher, $parametres['diagramme']);
        }

        //Code html du bloc d'affichage de la participation par entité
        $html_participation_entite = sprintf(
            $this->template_participation_entite,
            $parametres['panel'],
            $entite_infos['unite_libelle'],
            $entite_infos['inscrit'],
            $html_tableau_participation,
            $html_graph
        );
        return $html_participation_entite;
    }

    /**
     * COMPARAISON PARTICIPATION
     * Renvoie le code html du bloc réalisant l'affichage de la participation
     * globale enregistrée pour chaque élection demandée dans les paramétres
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string code html
     */
    protected function get_html_comparaison_participation($parametres) {
        // Récupération des paramétres d'affichage
        $params = $this->get_params();
        // Participation de l'élection affichée
        $partElectionAff = $this->get_participation_unite($params['unites']['perimetre']);
        if (empty($partElectionAff)) {
            return;
        }

        // Récupération de la liste des tranches horaires à afficher
        $horaires = array_map(function ($horaire) {
            return $horaire;
        }, array_keys($partElectionAff['participations']));

        // Récupération de la participation de chaque élection et création de la
        // liste donnant le nombre d'inscrit par election
        $partElections = array();
        $partElections[$this->identifier] = $partElectionAff;
        $inscritElection =  sprintf(
            "<li>%s : %d</li>\n",
            $partElectionAff['election'],
            $partElectionAff['inscrit']
        );
        if (array_key_exists('comparaison', $params) && ! empty($params['comparaison'])) {
            foreach ($params['comparaison'] as $idElection) {
                if (! empty($idElection)) {
                    $infoElection = $this->get_participation_globale_autre_election($idElection);
                    if (! empty($infoElection)) {
                        $partElections[$idElection] = $infoElection;
                        $inscritElection .= sprintf(
                            "<li>%s : %d</li>\n",
                            $partElections[$idElection]['election'],
                            $partElections[$idElection]['inscrit']
                        );
                    }
                }
            }
        }

        // Nom des colonnes correspondant aux noms des élections
        $entete = array_map(function ($election) {
            return '<th>'.$election['election'].'</th>';
        }, $partElections);

        // Construction de la liste affichant le nombre d'inscrit par élection
        $htmlListeInscrit = sprintf(
            '<div> Inscrits par élection :
                <ul>
                    %s
                </ul>
            </div>',
            $inscritElection
        );

        // Récupération et affichage du nombre de votant par tranche horaire pour chaque
        // élection
        $contenuTableau = '';
        foreach ($horaires as $horaire) {
            $htmlPartTranche = '';
            // Récupération de la participation et du nombre de votant pour chaque tranche horaire
            // correspondante à celle de l'élection affichée
            // Si jamais la tranche n'existe pas affiche : - (0)
            foreach ($partElections as $election) {
                $taux = ' - ';
                $votants = '';
                if (array_key_exists($horaire, $election['participations'])) {
                    $votants = $election['participations'][$horaire]['votant'];
                    $votants = ! empty($votants) ? "( $votants )" : "( 0 )";
                    $taux = $election['participations'][$horaire]['tx'];
                }
                $htmlPartTranche .= sprintf(
                    '<td>%s %s</td>',
                    $taux,
                    $votants
                );
            }
            $contenuTableau .= sprintf(
                '<tr>
                    <td>%s</td>
                    %s
                </tr>',
                $horaire,
                $htmlPartTranche
            );
        }

        // Construction du tableau de la comparaison
        $htmlTableauComparaison = sprintf(
            '<table id="tab-comparaison" class="table table-bordered table-condensed table-striped">
                <tr>
                    <th>Elections</th>
                    %s
                </tr>
                %s
            </table>',
            implode("\n", $entete),
            $contenuTableau
        );

        //code html du bloc d'affichage de la participation
        $htmlComparaison = sprintf(
            $this->template_comparaison_participation,
            $parametres['panel'],
            $htmlListeInscrit,
            $htmlTableauComparaison
        );

        return $htmlComparaison;
    }

    /**
     * LISTE ENTITE
     * Renvoie le code html de la liste des entités
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string
     */
    protected function get_html_liste_unite($parametres) {
        $params = $this->get_params();
        $cliquable = array_key_exists('cliquable', $parametres) && $parametres['cliquable'] === 'oui';
        $entite_liste = $this->get_unites_by_type($params['unites']['perimetre'], $params['unites']['type']);
        if (!isset($entite_liste)) {
            return;
        }

        $theme = '';
        if (isset($_GET['theme'])) {
            $theme = '&amp;theme='.$_GET['theme'];
        }

        // Nombre d'élément à afficher
        $nombreEntite = count($entite_liste);
        $limite_basse = (intval($nombreEntite / 10) * 10);
        $limite_haute = $limite_basse + 9;

        // Récupération du titre de la sidebar
        $titreEntete = array_key_exists('titre', $parametres)
        && ! empty($parametres['titre']) ?
            $parametres['titre'] :
            'unités';

        // entête de la liste avec comme titre le type d'unité à afficher
        // l'entête contiens également des informations concernant le
        // nombre d'unité à afficher
        $html_liste = sprintf(
            '<ul class="nav nav-sidebar entite-%d entite-entre-%d-%d">
                <li class="nav-header">
                    %s
                </li>',
            $nombreEntite,
            $limite_basse,
            $limite_haute,
            $titreEntete
        );

        $first = true;
        $index = 0;

        foreach ($entite_liste as $entite) {
            //cet index permet d'avoir un identifiant unique pour chaque
            //unités ce qui facilite leur identification, notamment pour
            //les tests
            $index++;
            //récupération des infos de l'unité pour affichage
            $uniteInfos = $this->get_unite_infos($entite);
            // Si les infos ont bien été récupérées alors l'unité est ajoutée à la liste
            if (! empty($uniteInfos)) {
                //définition du html de la classe pour chaque unité
                // first : premier élément de la liste
                $html_class_unite = '';
                if ($first == true) {
                    $html_class_unite .= 'first ';
                    $first = false;
                }
                // arrived / wait : les unités sont présentes pour affichage ou pas
                if ($cliquable) {
                    $html_class_unite .= $uniteInfos['envoie'] == '1' ? 'arrived ' : 'wait ';
                }
                // active : unités sélectionnées actuellement
                $html_class_unite .= $entite == $_SESSION['b'] ? 'active' : '';
    
                //Code html du lien permettant pour l'affichage du résultat/de la participation
                //de l'entité
                $html_link = '';
                if ($cliquable || $uniteInfos['envoie'] == '1') {
                    // Affichage du lien
                    $html_link = sprintf(
                        '<a href="?identifier=%s&amp;b=%s&amp;idx=%s&amp;click=%s%S">',
                        $this->identifier,
                        $entite,
                        $this->get_election(),
                        ($_SESSION['click'] + 1),
                        $theme
                    );
                }
    
                //récupération du code de la class du glyphicon et fermeture de la
                //balise du href si nécessaire
                if (! $cliquable && $uniteInfos['envoie'] == '1') {
                    $html_class_glyphicon = 'ok';
                    $html_fermeture_balise = '</a>';
                } elseif (! $cliquable && $uniteInfos['envoie'] == '0') {
                    $html_class_glyphicon =  'time';
                    $html_fermeture_balise = '';
                } else {
                    $html_class_glyphicon =  'chevron-right';
                    $html_fermeture_balise = '</a>';
                }
    
                //code html du glyphicon
                $html_glyphicon = sprintf(
                    '<span class="glyphicon glyphicon-%s"><!-- --></span>
                        %s',
                    $html_class_glyphicon,
                    Encoding::toUTF8($uniteInfos['lib'])
                );
    
                //Code html de la l'entité dans la liste
                $html_liste .= sprintf(
                    '<li class="%s" id="unite-%d">
                        %s
                        %s
                        %s
                    </li>',
                    $html_class_unite,
                    $index,
                    $html_link,
                    $html_glyphicon,
                    $html_fermeture_balise
                );
            }
        }
        $html_liste .= '</ul>';
        //Affichage de la liste
        return $html_liste;
    }

    /**
     * Renvoie le code html de la repartition des sièges pour le conseil
     * communautaire
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string
     */
    protected function get_html_sieges_communautaire($parametres) {
        //Récupération des données nécessaires à l'affichage
        $repartitionSieges = $this->get_repartition_sieges();
        //Vérification que les données existent
        if (empty($repartitionSieges)) {
            return;
        };

        $donneesAAfficher = array();
        //Récuperation du nombre de sièges obtenus par chaque partie
        //et code html du tableau contenant ces résultats
        $html_tableau_siege = '';
        
        // Tri par numéro d'ordre des listes/candidats
        ksort($repartitionSieges['siege_lc']);
        foreach ($repartitionSieges['siege_lc'] as $codeListe => $repartition) {
            $liste = $this->get_infos_candidat($codeListe);
            $html_tableau_siege .= sprintf(
                $this->template_tableau_siege,
                $codeListe,
                $liste['libelle_liste'],
                $liste['couleur'],
                $repartition
            );
            //Remplissage du tableau contenant les données à afficher
            $donneesAAfficher[$codeListe] = array(
                'valeur' => $repartition,
                'couleur' => $liste['couleur']
            );
        }

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            $html_graph = $this->get_html_canvas($parametres, 'chartSiegesCom');
            $this->get_script_chart('chartSiegesCom', $donneesAAfficher, $parametres['diagramme']);
        }

        $html_sieges_communautaire = sprintf(
            $this->template_sieges_communautaire,
            $parametres['panel'],
            $html_tableau_siege,
            $html_graph
        );
        return $html_sieges_communautaire;
    }

    /**
     * Renvoie le code html de la repartition des sièges pour le conseil
     * municipal
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string
     */
    protected function get_html_sieges_municipal($parametres) {
        //Récupération des données nécessaires à l'affichage
        $repartitionSieges = $this->get_repartition_sieges();
        //Vérification que les données existent
        if (empty($repartitionSieges)) {
            return;
        };

        $donneesAAfficher = array();
        //Récuperation du nombre de sièges obtenus par chaque partie
        //et code html du tableau contenant ces résultats
        $html_tableau_siege = '';

        // Tri par numéro d'ordre des listes/candidats
        ksort($repartitionSieges['siege_lm']);
        foreach ($repartitionSieges['siege_lm'] as $codeListe => $repartition) {
            $liste = $this->get_infos_candidat($codeListe);
            $html_tableau_siege .= sprintf(
                $this->template_tableau_siege,
                $codeListe,
                $liste['libelle_liste'],
                $liste['couleur'],
                $repartition
            );
            //Remplissage du tableau contenant les données à afficher
            $donneesAAfficher[$codeListe] = array(
                'valeur' => $repartition,
                'couleur' => $liste['couleur']
            );
        }

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            $html_graph = $this->get_html_canvas($parametres, 'chartSiegesMun');
            $this->get_script_chart('chartSiegesMun', $donneesAAfficher, $parametres['diagramme']);
        }

        $html_sieges_municipal = sprintf(
            $this->template_sieges_municipal,
            $parametres['panel'],
            $html_tableau_siege,
            $html_graph
        );
        return $html_sieges_municipal;
    }

    /**
     * Renvoie le code html de la repartition des sièges pour le conseil
     * metropolitain
     *
     * @param array $parametres : contiens tous les paramètres du blocs
     * @return string
     */
    protected function get_html_sieges_metropolitain($parametres) {
        //Récupération des données nécessaires à l'affichage
        $repartitionSieges = $this->get_repartition_sieges();
        //Vérification que les données existent
        if (empty($repartitionSieges) ||
            ! array_key_exists('siege_lmep', $repartitionSieges)
        ) {
            return;
        };

        $donneesAAfficher = array();
        //Récuperation du nombre de sièges obtenus par chaque partie
        //et code html du tableau contenant ces résultats
        $html_tableau_siege = '';
        // Tri par numéro d'ordre des listes/candidats
        ksort($repartitionSieges['siege_lmep']);
        foreach ($repartitionSieges['siege_lmep'] as $codeListe => $repartition) {
            $liste = $this->get_infos_candidat($codeListe);
            $html_tableau_siege .= sprintf(
                $this->template_tableau_siege,
                $codeListe,
                $liste['libelle_liste'],
                $liste['couleur'],
                $repartition
            );
            //Remplissage du tableau contenant les données à afficher
            $donneesAAfficher[$codeListe] = array(
                'valeur' => $repartition,
                'couleur' => $liste['couleur']
            );
        }

        //Code html de la zone de dessin du graphique et
        //récupération du script du graphique
        $html_graph = '';
        if (array_key_exists('diagramme', $parametres) && !empty($parametres['diagramme'])) {
            $html_graph = $this->get_html_canvas($parametres, 'chartSiegesMep');
            $this->get_script_chart('chartSiegesMep', $donneesAAfficher, $parametres['diagramme']);
        }

        $html_sieges_metropolitain = sprintf(
            $this->template_sieges_metropolitain,
            $parametres['panel'],
            $html_tableau_siege,
            $html_graph
        );
        return $html_sieges_metropolitain;
    }

    /**
     * Ecris et renvoie le code html du canvas. Utilise le template du canvas,
     * les dimensions paramétrées et l'id du canvas pour préparer la balise
     * <canvas> servant à afficher le diagramme.
     *
     * @param array $parametres tableau de paramétrage du bloc dans lequel
     * le canvas est intégré
     * @param string $idCavas id de la balise Canvas qui servira ensuite
     * à placer le diagramme
     */
    protected function get_html_canvas($parametres, $idCanvas) {
        //Récupération des dimensions du canvas si elles ont été paramétrées
        $hauteur_diagramme = array_key_exists('hauteur_diagramme', $parametres) &&
            $parametres['hauteur_diagramme'] > 0 ?
            'height="'.$parametres['hauteur_diagramme'].'"':
            '';
        $largeur_diagramme = array_key_exists('largeur_diagramme', $parametres) &&
            $parametres['largeur_diagramme'] > 0 ?
            'width="'.$parametres['largeur_diagramme'].'"':
            '';
        //Recupération du code html du canvas en insérant dans le templates
        //les dimensions parémétrées et son id
        $html_canvas = sprintf(
            $this->template_canvas,
            $idCanvas,
            $hauteur_diagramme,
            $largeur_diagramme
        );
        return $html_canvas;
    }

    /**
     * @var array
     */
    protected $unites_infos = array();

    /**
     * @var array
     */
    protected $resultats_unites = array();

    /**
     * @var array
     */
    protected $participation_unites = array();

    /**
     * @var array
     */
    protected $perimetres = array();

    /**
     * @var array
     */
    protected $repartition_sieges = array();

    /**
     * Remplis les infos relatives aux unites de l'életion :
     *   - code   : integer  code/numéro d'ordre de l'unité
     *   - envoie : boolean  true -> unité envoyée à l'affichage, false : non envoyée
     *   - type   : integer  type de l'unité (BV, canton, etc)
     *   - lib    : string   libelle de l'unité
     *   - is_last: boolean  true : dernière unité envoyée à l'anffichage
     *
     */
    protected function set_unites_infos() {
        $unites = array();
        //Récupération du json contenant les informations, puis décodage du json
        //pour obtenir un tableau associatif. Pour finir stocke le tableau dans
        //la propriété $unites_infos
        if (file_exists(AFF_ELECTION_RESULTS_PATH."unites.json")) {
            $jsonUnites = file_get_contents(AFF_ELECTION_RESULTS_PATH."unites.json");
            $unites = json_decode($jsonUnites, true);
        }
        $this->unites_infos = $unites;
    }

    /**
     * Récupère et renvoie les informations de l'unité, à savoir :
     *   - son type
     *   - son libelle
     *   - son etat : envoyé ou pas
     *   - son code
     *   - si c'est la dernière envoyée à l'affichage
     *
     * @param integer $unite : id de l'unité
     *
     * @return array informations de l'unité
     */
    protected function get_unite_infos($unite) {
        $infosUnite = array();
        if (array_key_exists($unite, $this->unites_infos)) {
            $infosUnite = $this->unites_infos[$unite];
        }
        return $infosUnite;
    }

    /**
     * Récupère et renvoie les informations des unités, à savoir :
     *   - leur type
     *   - leur libelle
     *   - leur etat : envoyé ou pas
     *   - leur code
     *   - si c'est la dernière envoyée à l'affichage
     *
     * @return array informations de l'unité
     */
    protected function get_unites_infos() {
        return $this->unites_infos;
    }

    /**
     * Setter de resultats_unites.
     * Récupération pour chaque unité du json si le fichier existe. Ensuite, il est
     * décodé pour obtenir un tableau associatif. Pour finir, vérifie pour chaque candidat
     * si il existe un fichier contenant sa photo. Le chemin vers la photo est ajouté dans le
     * tableau des résultats du candidats.
     * Le tableau final est ensuite stockée dans le paramètre resultats_unites.
     * Permet aussi de compter le nombre de candidat de l'élection et de stocker
     * ce nombre
     */
    protected function set_resultats_unites() {
        //Récupération de la liste des unites stockée dans unites_infos
        $unitesInfos = $this->get_unites_infos();
        //Dans cette liste seul les id des unités sont nécessaires
        foreach (array_keys($unitesInfos) as $uniteId) {
            //Les résultats doivent être réinitailiser pour éviter,
            //si il n'y a pas de fichier trouvé, de copier les résultats
            //précedemment trouvé
            $resultats = array();
            if (file_exists(AFF_ELECTION_RESULTS_PATH."bres/b".$uniteId.".json")) {
                $contenuJson = file_get_contents(
                    AFF_ELECTION_RESULTS_PATH."bres/b".$uniteId.".json"
                );
                $resultats = json_decode($contenuJson, true);

                foreach (array_keys($resultats['candidats']) as $idCandidat) {
                    //Récupération du chemin vers la photo si le candidat en a une
                    $path = '';
                    //Recherche le fichier contenant la photo du candidat, quelle que
                    //soit son extension
                    $path_to_test = glob('res/'.$this->election."/photo/".$idCandidat.".*");
                    //La méthode glob() renvoie un tableau contenant tous les résultats
                    //trouvés. Il n'y a qu'une seule image donc on récupère le premier résultat
                    if (isset($path_to_test[0]) && file_exists($path_to_test[0])) {
                        $path = $path_to_test[0];
                    }
                    $resultats['candidats'][$idCandidat]['photo'] = $path;
                }
            }
            $this->resultats_unites[$uniteId] = $resultats;
        }
    }

    /**
     * Récupére et renvoie le tableau contenant les résultats
     * de l'unité.
     *
     * @param integer $unite : id de l'unité
     *
     * @return array $uniteResult : tableau des résultats
     */
    protected function get_resultats_unite($unite) {
        $res = array();
        if (array_key_exists($unite, $this->resultats_unites)) {
            $res = $this->resultats_unites[$unite];
        }
        return $res;
    }

    /**
     * Setter de participation_unites.
     * Récupération pour chaque unité du json si le fichier existe. Ensuite, il est
     * décodé pour obtenir un tableau associatif.
     * Au final, un tableau ayant pour clés les id des unités et pour valeur leurs
     * participation est obtenu.
     */
    protected function set_participation_unites() {
        //Récupération de la liste des unites stockée dans unites_infos
        $unitesInfos = $this->get_unites_infos();
        //Dans cette liste seul les id des unités sont nécessaires
        foreach (array_keys($unitesInfos) as $uniteId) {
            $participation = array();
            if (file_exists(AFF_ELECTION_RESULTS_PATH."bpar/b".$uniteId.".json")) {
                $contenuJson = file_get_contents(
                    AFF_ELECTION_RESULTS_PATH."bpar/b".$uniteId.".json"
                );
                $participation = json_decode($contenuJson, true);
            }
            $this->participation_unites[$uniteId] = $participation;
        }
    }

    /**
     * Récupére et renvoie le tableau contenant la participation
     * de chaque unité
     *
     * @return array $uniteResult : tableau de la participation
     */
    protected function get_participation_unites() {
        return $this->participation_unites;
    }

    /**
     * Récupére et renvoie le tableau contenant la participation
     * de l'unité.
     *
     * @param integer $unite : id de l'unité
     *
     * @return array $uniteResult : tableau de la participation
     */
    protected function get_participation_unite($unite) {
        $participation =  array();
        if (array_key_exists($unite, $this->participation_unites)) {
            $participation = $this->participation_unites[$unite];
        }
        return $participation;
    }
    
    /**
     * Récupére et renvoie le tableau contenant la répartition des
     * sièges.
     * @return array : tableau de la répartition
     */
    protected function get_repartition_sieges() {
        return $this->repartition_sieges;
    }

    /**
     * Récupére et renvoie le tableau contenant la répartition des
     * sièges.
     * @return array : tableau de la répartition
     */
    protected function set_repartition_sieges() {
        $repartition = array();
        if (file_exists(AFF_ELECTION_RESULTS_PATH."repartition_sieges.json")) {
            $contenuJson = file_get_contents(AFF_ELECTION_RESULTS_PATH."repartition_sieges.json");
            $repartition = json_decode($contenuJson, true);
        }
        $this->repartition_sieges = $repartition;
    }

    /**
     * Setter de perimetres.
     * Récupération du json si le fichier existe. Ensuite, il est
     * décodé pour obtenir un tableau associatif que l'on stocke dans perimetres
     */
    protected function set_perimetres() {
        $perimetres = array();
        if (file_exists(AFF_ELECTION_RESULTS_PATH."perimetres.json")) {
            $contenuJson = file_get_contents(AFF_ELECTION_RESULTS_PATH."perimetres.json");
            $perimetres = json_decode($contenuJson, true);
        }
        $this->perimetres = $perimetres;
    }

    protected function set_repartition() {
        /**
         * Sieges de conseillers municipaux et de conseillers communautaires
         * sieges_lm.inc
         */
        $siege_lm = array();
        $siege_lc = array();
        $noliste_lm = array();
        if (file_exists(AFF_ELECTION_RESULTS_PATH."sieges_lm.inc")) {
            include AFF_ELECTION_RESULTS_PATH."sieges_lm.inc";
        }
        $this->infos["sieges"] = array(
            "listes" => $noliste_lm,
            "sieges_cm" => $siege_lm,
            "sieges_cc" => $siege_lc,
        );
    }

    /**
     * Setter des paramètres de l'animation
     * @return void
     */
    protected function set_params() {
        //paramétrage par défaut
        $param = array(
            'entete' => array(
                'titre' => 'Animation',
                'sous_titre' => 'Provisoire',
                'couleur_titre' => '#000000',
                'couleur_bandeau' => '#ffffff'
            ),
            'animation' => array(
                'refresh' => 60,
                'feuille_style' => '',
                'script' => ''
            )
        );
        //Récupération du paramétrage
        if (file_exists(AFF_ELECTION_RESULTS_PATH.'animation_'.$this->identifier.'/param.ini')) {
            $ini = parse_ini_file(
                AFF_ELECTION_RESULTS_PATH.'animation_'.$this->identifier.'/param.ini',
                true
            );
            // Vérifie si un périmètre a été choisi, si ce n'est pas la cas renvoie un tableau vide
            if (! key_exists('perimetre', $ini['unites']) || empty($ini['unites']['perimetre'])) {
                echo 'Veuillez sélectionner un périmètre';
                return array();
            }
            // Vérifie si un type d'unité a été choisi, si ce n'est pas la cas renvoie un tableau
            // vide
            if (! key_exists('type', $ini['unites']) || empty($ini['unites']['type'])) {
                echo 'Veuillez sélectionner un type d\'unité';
                return array();
            }
            //Le merge permet d'avoir des valeurs par défaut pour les blocs
            //même si ils n'ont pas été paramétré ce qui évite les erreurs
            //lors de l'affichage
            $param = array_merge($param, $ini);
            $electionsComparaison = explode(';', $param['comparaison']['election']);
            $param['comparaison'] = $electionsComparaison;
            // Ajout du script avec les autres script
            $this->add_to_jscript('<script>'.$ini['animation']['script'].'</script>');
        }

        //Recherche le fichier contenant le logo, quelle que soit son extension
        $path_to_test = glob('res/'.$this->election.'/animation_'.$this->identifier."/logo.*");
        //La méthode glob() renvoie un tableau contenant tous les résultats
        //trouvés. Il n'y a qu'un seul logo donc on récupère le premier résultat
        if (!empty($path_to_test) && file_exists($path_to_test[0])) {
            $param['logo'] = $path_to_test[0];
        }


        //stockage des paramétres
        $this->params = $param;
    }

    /**
     * Getter du tableau de paramétrage des blocs de l'animation
     * @return array
     */
    protected function get_params_blocs() {
        return $this->params_blocs;
    }

    /**
     * Setter du paramétrage des blocs de l'animation
     * @return void|boolean
     */
    protected function set_param_blocs() {
        //par défaut aucun bloc n'est affiché
        $paramBlocs = array();
        //Récupération du paramétrage
        if (file_exists(AFF_ELECTION_RESULTS_PATH.'animation_'.$this->identifier.'/blocs.ini')) {
            $paramBlocs = parse_ini_file(
                AFF_ELECTION_RESULTS_PATH.'animation_'.$this->identifier.'/blocs.ini',
                true,
                INI_SCANNER_RAW
            );
            if (! $paramBlocs) {
                return false;
            }
        }

        //Paramétrage par défaut :
        //  1- POur la sidebar
        //     * Position = droite
        //     * taille = 4
        //  2- Pour les blocs
        //     * panel=primary
        //     * taille=4
        if (array_key_exists('sidebar', $paramBlocs)) {
            if (empty($paramBlocs['sidebar']['taille'])) {
                $paramBlocs['sidebar']['taille'] = '4';
            }
            if (empty($paramBlocs['sidebar']['position'])) {
                $paramBlocs['sidebar']['position'] = 'droite';
            }
        }
        foreach ($paramBlocs as $key => $bloc) {
            if ($key !== 'sidebar') {
                if (!array_key_exists('panel', $bloc) || empty($bloc['panel'])) {
                    $paramBlocs[$key]['panel'] = 'primary';
                }
                if (!array_key_exists('taille', $bloc) || empty($bloc['taille'])) {
                    $paramBlocs[$key]['taille'] = '4';
                }
            }
        }
        //stockage des paramétres
        $this->params_blocs = $paramBlocs;
    }

    /**
     * Récupère la liste des unités appartennant au perimetre et ayant
     * le type recherché. Pour chaque élément de cette liste vérifie
     * son état. Si l'unité a été envoyé alors elle est ajouté à la
     * liste des unités à afficher
     *
     * @return array liste des unites à afficher
     */
    protected function get_liste_unite_defile() {
        $unites = $this->get_unites_infos();
        $params = $this->get_params();
        $unitesAAfficher = array();
        if (empty($unites)) {
            return $unitesAAfficher;
        }
        $unitesPerimetre = $this->get_unites_by_type($params['unites']['perimetre'], $params['unites']['type']);
        foreach ($unitesPerimetre as $idUnite) {
            if ($unites[$idUnite]['envoie'] === true) {
                $unitesAAfficher[] = $idUnite;
            }
        }
        return $unitesAAfficher;
    }


    /**
     * Renvoie un tableau contenant la liste des identifiants des unités
     * enfant.
     *
     * @param integer $unite_parent identifiant de l'unité dont on veut
     * récupérer les enfants
     *
     * @return array $unitesEnfant liste des unités enfants
     */
    protected function get_unite_enfant($unite_parent) {
        $unitesEnfant = array();
        if (array_key_exists($unite_parent, $this->perimetres)) {
            $unitesEnfant = $this->perimetres[$unite_parent];
        }
        return $unitesEnfant;
    }

    /**
     * Récupére toutes les unités descendantes de l'unité passé en paramètre.
     * Vérifie pour chacune de ces unités si leur type correspond au type voulu.
     * Si c'est le cas l'identifiant l'identifiant de l'unité est stocké dans un
     * tableau.
     * Renvoie un tableau contenant la liste des identifiants des unités descendants
     * de l'unité parent et dont le type correspond à celui recherché.
     *
     * @param integer $unite_parent identifiant de l'unité dont on veut
     * récupérer les descendants
     * @param integer $type_voulu identifiant du type recherché
     *
     * @return array $enfantsOfWantedType
     */
    protected function get_unites_by_type($unite_parent, $type_voulu) {
        if (empty($type_voulu)) {
            return $this->get_unite_enfant($unite_parent);
        }
        $descendants = array();

        //Si le type recherché est celui du parent alors seul le parent
        //est retourné. Cela permet d'afficher le perimetre parent seul
        //si on le désire
        $infoParent = $this->get_unite_infos($unite_parent);
        if (! empty($infoParent) &&
            array_key_exists('type', $infoParent) &&
            $type_voulu === $infoParent['type']) {
            $descendants[] = $unite_parent;
            return $descendants;
        }

        $unitesToTest[] = $unite_parent;
        $currentUnite = array_shift($unitesToTest);

        //Récupération de tous les descendants de l'unite
        while (! empty($currentUnite)) {
            $enfants = $this->get_unite_enfant($currentUnite);
            $descendants = array_merge($descendants, $enfants);
            $unitesToTest = array_merge($unitesToTest, $enfants);
            $currentUnite = array_shift($unitesToTest);
        }

        //Pour chaque descendant, récupère son type et si il correspond
        //au type voulu, on stocke l'id du descendant dans le tableau
        //des résultats
        $ordreUnites = array();
        foreach ($descendants as $descendant) {
            $infoUnite = $this->get_unite_infos($descendant);
            if (! empty($infoUnite) &&
                array_key_exists('type', $infoUnite) &&
                $infoUnite['type'] === $type_voulu) {
                $ordreUnites[$descendant] = $infoUnite['ordre'];
            }
        }
        // Tri les unités par ordre puis récupère uniquement les identifiants des unités
        asort($ordreUnites);
        $enfantsOfWantedType = ! empty(array_keys($ordreUnites)) ?
            array_keys($ordreUnites) :
            array();
        return $enfantsOfWantedType;
    }


    /**
     * Récupère à partir du paramétrage le type de diagramme voulu.
     * Selon le diagramme choisit formatte les données pour quelle
     * puissent être utilisées dans le script du diagramme.
     * A l'aide des données formattées prépare le script du diagramme.
     * Ajoute le script à la liste des jscripts pour affichage.
     *
     * @param string $idCanvas id du canvas où le diagramme doit être affiché
     * @param array $donneesAAfficher tableau contenant les informations nécessaire
     * pour l'affichage.
     * Ex : $donneesAAfficher['label'] = array(
     *          'valeur' => 1,
     *          'couleur' => 'cdcdcd'
     *      );
     * @param string $typeChart type de diagramme à afficher :
     * - bar
     * - pie
     * -doughnut
     */
    protected function get_script_chart($idCanvas, $donneesAAfficher, $chartType) {
        // Formattage des données du tableau pour pouvoir les afficher
        // Pour l'affichage, il faut avoir des chaînes de caractére et
        // les labels et couleurs doivent être entre ""
        $labels = array_map(function ($donnees) {
            return '"'.$donnees.'"';
        }, array_keys($donneesAAfficher));
        $labels = implode(', ', $labels);

        $datas = array_map(function ($donnees) {
            return $donnees['valeur'];
        }, $donneesAAfficher);
        $datas = implode(', ', $datas);

        $colors = array_map(function ($donnees) {
            return '"'.$donnees['couleur'].'"';
        }, $donneesAAfficher);
        $colors = implode(', ', $colors);

        //Récupération du script du diagramme choisi dans les paramètres
        switch ($chartType) {
            case 'camembert':
                $script = $this->script_graph_pie($idCanvas, $labels, $datas, $colors);
                break;
            case 'donut':
                $script = $this->script_graph_doughnut($idCanvas, $labels, $datas, $colors);
                break;
            case 'histogramme':
                $script = $this->script_graph_bar($idCanvas, $labels, $datas, $colors);
                break;
            default:
                $script = '';
                break;
        }
        //Affichage du script
        $this->add_to_jscript($script);
    }

    /**
     * Ecris le script d'affichage d'un histogramme
     *
     * @param string $idCanvas id de la balise canvas
     * @param string $labels liste des labels à afficher
     * @param string $data liste des valeurs à afficher
     *
     * @return string script du diagramme
     */
    protected function script_graph_bar($idCanvas, $labels, $data, $colors) {
        $bar_script = sprintf(
            "<script type='text/javascript'>
            var data = {
                labels: [%s],
                datasets: [{
                    data: [%s],
                    backgroundColor: [%s]
                }]
            };
            var options = {
                maintainAspectRatio: false,
                legend: false,
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true
                        }
                    }]
                }
            };
            var ctx = document.getElementById('%s').getContext('2d');
            new Chart(ctx, {
                type: 'bar',
                data: data,
                options: options
            });
            </script>",
            $labels,
            $data,
            $colors,
            $idCanvas
        );
        return $bar_script;
    }

    /**
     * Script d'affichage d'un camenbert
     *
     * @param string $idCanvas id de la balise canvas
     * @param string $data liste des données à affichées de la forme
     * data[0] = {value: valeur_de_0, color: #couleur_de_0}
     *
     * @return string script du diagramme
     */
    protected function script_graph_pie($idCanvas, $labels, $datas, $colors) {
        $pie_script = sprintf(
            "<script type='text/javascript'>
            var data = {
                labels: [%s],
                datasets: [{
                    data: [%s],
                    backgroundColor: [%s]
                }]
            };
            var options = {
                maintainAspectRatio: false,
                legend: false,
                animation: {
                    animateScale: false,
                    animateRotate: true
                }
            };
            var ctx = document.getElementById('%s').getContext('2d');
            new Chart(ctx, {
                type: 'pie',
                data: data,
                options: options
            });
            </script>",
            $labels,
            $datas,
            $colors,
            $idCanvas
        );
        return $pie_script;
    }

    /**
     * Script d'affichage d'un donut
     *
     * @param string $idCanvas id de la balise canvas
     * @param string $data liste des données à affichées de la forme
     * data[0] = {value: valeur_de_0, color: #couleur_de_0}
     *
     * @return string script du diagramme
     */
    protected function script_graph_doughnut($idCanvas, $labels, $datas, $colors) {
        $doughnut_script = sprintf(
            "<script type='text/javascript'>
            var data = {
                labels: [%s],
                datasets: [{
                    data: [%s],
                    backgroundColor: [%s]
                }]
            };
            var options = {
                maintainAspectRatio: false,
                legend: false,
                animation: {
                    animateScale: false,
                    animateRotate: true
                }
            };
            var ctx = document.getElementById('%s').getContext('2d');
            new Chart(ctx, {
                type: 'doughnut',
                data: data,
                options: options
            });
            </script>",
            $labels,
            $datas,
            $colors,
            $idCanvas
        );
        return $doughnut_script;
    }

    /**
     * Setter de la liste des couleurs de l'animation
     * @return void
     */
    protected function set_colors() {
        //
        $this->colors = array(
            "#BBD597","#A5946b","#6FBA84","#88F1C6","#A5A93F","#BB8697","#3D7EB7",
            "#6F6584","#EF941B","#C35D08","#84BC40","#07DCDA","#8BCD85","#688EE4",
            "#57234C","#DD3360","#64A5E3","#DFFB81","#CCBD92","#A5003F","#00A0E6",
            "#09A93F","#DF0997","#6FBA09","#09A0E6","#A5093F","#A50009","#0009E6",
            "#A0A93F","#A00997","#A0BA09","#A0A0E6"
        );
    }

    /**
     * Récupère une couleurs par son id
     * @param integer $id identifiant de la couleur
     * @return string code de la couleur ou "cdcdcd" si elle n'a pas été trouvée
     */
    protected function get_color($id = 0) {
        //
        if ($this->colors == NULL) {
            $this->set_colors();
        }
        //
        if (isset($this->colors[$id])) {
            return $this->colors[$id];
        } else{
            return "cdcdcd";
        }
    }

    /**
     * Compte le nombre d'unité ayant été envoyées à l'affichage
     *
     * @return integer nombre d'unité envoyées à l'affichage
     */
    protected function compte_unites_arrivees() {
        $unites = $this->get_unites_infos();
        $nbUnites = 0;
        foreach ($unites as $unite) {
            if ($unite['envoie']) {
                $nbUnites++;
            }
        }
        return $nbUnites;
    }

    /**
     * @var array
     */
    protected $infos_candidats = array();

    /**
     * Remplis le tableau contenant les infos relatives aux candidats de l'élection :
     *   - ordre          : integer  numero d'ordre du candidat
     *   - libelle        : string   nom du candidat
     *   - libelle_liste   : string   nom 2 du candidat
     *   - age_moyen      : string   age moyen
     *   - age_moyen_com  : string   age moyen de la liste communautaire
     *   - couleur        : string   couleur de l'affichage du candidat
     *
     */
    protected function set_infos_candidats() {
        //Récupération du json contenant les informations, puis décodage du json
        //pour obtenir un tableau associatif. Pour finir stocke le tableau dans
        //la propriété $infos_candidats
        $infosCandidats = array();
        if (file_exists(AFF_ELECTION_RESULTS_PATH."candidats.json")) {
            $candidats = file_get_contents(AFF_ELECTION_RESULTS_PATH."candidats.json");
            $infosCandidats = json_decode($candidats, true);
        }
        //Récupération du chemin vers la photo du candidat et ajout dans le tableau
        foreach ($infosCandidats as $ordre => $candidat) {
            $infosCandidats[$ordre]['photo'] = '';
            //Recherche le fichier contenant la photo, quelle que soit son extension
            $path_to_test = glob('res/'.$this->election.'/photo/'.$candidat['ordre'].'.*');
            //La méthode glob() renvoie un tableau contenant tous les résultats
            //trouvés. Il n'y a qu'une seule image donc on récupère le premier résultat
            if (!empty($path_to_test) && file_exists($path_to_test[0])) {
                $infosCandidats[$ordre]['photo'] = $path_to_test[0];
            }
        }
        $this->infos_candidats = $infosCandidats;
    }

    protected function get_infos_candidats() {
        return $this->infos_candidats;
    }

    protected function get_infos_candidat($idCandidat) {
        $infosCandidats = array();
        if (array_key_exists($idCandidat, $this->infos_candidats)) {
            $infosCandidats = $this->infos_candidats[$idCandidat];
        }
        return $infosCandidats;
    }

    /**
     * Récupère les infos contenues dans le fichier de participation de l'autre
     * élection.
     * Pour avoir la participation globale ce sont les infos issue du fichier
     * correspondant au périmètre de l'élection qui sont récupérées
     *
     * @param integer $idElection identifiant d'une élection dont les résultats
     * sont disponibles à l'affichage
     * @param integer $idUnite identifiant de l'unité devant être affichée
     *
     * @return mixed array|false participation enregistrée pour l'unité ou false
     * si la participation n'a pas pu être récupérée
     */
    protected function get_participation_globale_autre_election($idElection) {
        $participation = array();
        // Récupération du périmètre de l'élection
        if (file_exists(AFF_RESULTS_PATH.$idElection.'/perimetres.json')) {
            $contenuJson = file_get_contents(
                AFF_RESULTS_PATH.$idElection.'/perimetres.json'
            );
            $perimetres = json_decode($contenuJson, true);
            $perimetreGlob = null;
            foreach (array_keys($perimetres) as $parent) {
                $isPerimetreGlob = true;
                foreach ($perimetres as $enfants) {
                    if (in_array($parent, $enfants)) {
                        $isPerimetreGlob = false;
                        break;
                    }
                }
                if ($isPerimetreGlob) {
                    $perimetreGlob = $parent;
                    break;
                }
            }
        }

        // Si le fichier de la participation de l'autre élection existe son contenu
        // est récupéré et décodé pour avoir un tableau de la participation
        if (! empty($perimetreGlob) &&
            file_exists(AFF_RESULTS_PATH.$idElection."/bpar/b".$perimetreGlob.".json")) {
            $contenuJson = file_get_contents(
                AFF_RESULTS_PATH.$idElection."/bpar/b".$perimetreGlob.".json"
            );
            $participation = json_decode($contenuJson, true);
        }
        return $participation;
    }

    /**
     * Calcul les résultats enregistrés pour les unités arrivées et dans le
     * périmètre choisi.
     * Remarque : Ces résultats ne sont pas égaux à ceux du périmètres car les
     * résultats du périmètres prennent en compte toutes les unités même celles
     * n'ayant pas été envoyées à l'affichage.
     * La valeur du périmètre et celle du type d'unités est récupéré dans les
     * paramètre
     *
     * @return array résultats des unités envoyées à l'affichage
     */
    protected function calcul_resultats_unites_arrivees() {
        //Récupère les paramétres pour connaître le périmètre d'affichage et le type
        //d'unité à afficher
        $params = $this->get_params();
        //Récupère la liste des unités dont on souhaite avoir les résultats
        //On récupère la liste des unités ayant le type voulu pour calculer les
        //résultats que pour ces unités mais également les erreurs.
        //Si le calcul était réalisé sur les toutes les unités, les résultats des
        //unités et de leur périmètres seraient sommés et le total serait donc faux.
        $unites = $this->get_unites_by_type($params['unites']['perimetre'], $params['unites']['type']);
        //Initialisation des résultats que l'on souhaite calculer.
        $resultats = array(
            'inscrit' => 0,
            'votant' => 0,
            'emargement' => 0,
            'procuration' => 0,
            'blanc' => 0,
            'nul' => 0,
            'exprime' => 0
        );

        //récupération du nombre de candidats pour pouvoir initialiser le tableau des
        //résultats des candidats
        $candidatsInfos = $this->get_infos_candidats();
        foreach ($candidatsInfos as $ordre => $candidat) {
            $resultats['candidats'][$ordre] = array(
                'nom' => $candidat['libelle'],
                'prenom' => $candidat['libelle_liste'],
                'voix' => 0,
                'tx' => 0
            );
        }

        //Pour chacun des résultats à calculer et pour chaque unites de la liste,
        //vérifie si l'unité a été envoyée et, si c'est le cas, ajoute son résultat
        //au résultat total
        foreach ($unites as $uniteId) {
            $uniteInfo = $this->get_unite_infos($uniteId);
            //Le calcul des résultats n'est effectué que pour les unités envoyées à l'affichage
            if ($uniteInfo['envoie']) {
                $resultatsUnite = $this->get_resultats_unite($uniteId);
                //Somme les résultats pour chaque résultats dont on cherche le total
                foreach (array_keys($resultats) as $resultat) {
                    if (! empty($resultatsUnite[$resultat])) {
                        $resultats[$resultat] += $resultatsUnite[$resultat];
                    }
                }
                //Somme les voix obtenus pour chaque candidat et recalcule le taux de vote
                //en utilisant le nombre de vote exprimé calculé
                foreach (array_keys($resultats['candidats']) as $index) {
                    //Calcul du total de voix obtenus par le candidat et mise à jour du taux
                    $voix = null;
                    if (is_array($resultatsUnite) === true
                        && array_key_exists("candidats", $resultatsUnite) === true
                        && is_array($resultatsUnite['candidats']) === true
                        && array_key_exists($index, $resultatsUnite['candidats']) === true
                        && is_array($resultatsUnite['candidats'][$index]) === true
                        && array_key_exists("voix", $resultatsUnite['candidats'][$index]) === true) {
                        $voix = $resultatsUnite['candidats'][$index]['voix'];
                    }
                    if (! empty($voix)) {
                        $resultats['candidats'][$index]['voix'] += $voix;
                        $totalCandidat = $resultats['candidats'][$index]['voix'];
                        $exprimes = $resultats['exprime'];
                        $resultats['candidats'][$index]['tx'] = number_format(($totalCandidat / $exprimes) * 100, 2).'%';
                    }
                }
            }
        }
        //Renvoie la liste des résultats
        return $resultats;
    }

    /**
     * Récupère l'id de l'élection
     *
     * @return integer
     */
    protected function get_election(){
        return $this->election;
    }

    /**
     * Récupère le tableau des paramètres de l'élection
     *
     * @return array
     */
    protected function get_params(){
        return $this->params;
    }

    /**
     *
     * @return jscript
     */
    protected function get_jscript(){
        return $this->jscript;
    }

    /**
     * Ajoute des élements à l'attribut jscript
     *
     * @return void
     */
    protected function add_to_jscript($ajout){
        $this->jscript .= $ajout;
    }

    /**
     * Template du header du fichier html
     *
     * @var string
     */
    protected $template_html_header = '<!DOCTYPE html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="refresh" content="%1$s">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>R&eacute;sultats &eacute;lectoraux</title>
    <link href="themes/%2$s/css/bootstrap.min.css" rel="stylesheet">
    <link href="themes/%2$s/css/style.css" rel="stylesheet">
    <style>%3$s</style>
  </head>
  <body>';

    /**
     * Template du footer html
     *
     * @var string
     */
    protected $template_html_footer = '
    <!-- JavaScript -->
    <script src="themes/%1$s/js/jquery.min.js"></script>
    <script src="themes/%1$s/js/bootstrap.min.js"></script>
    <script src="themes/%1$s/js/Chart.min.js"></script>
    <script src="themes/%1$s/js/script.js"></script>
    %2$s
  </body>
</html>';

    /**
     * Template du tableau des résultats
     *
     * @var string
     */
    protected $template_resultats_table = '
<table class="table table-bordered table-condensed table-striped resultats-resultats">
  <thead>
    <tr class="resultat_titre">
      <th>Candidat / Liste</th>
      <th class="text-center">Voix</th>
      <th class="text-center">%%</th>
    </tr>
  </thead>
  <tbody>%s
  </tbody>
</table>';

    /**
     * Template d'une lige de résultat
     *
     * @var string
     */
    protected $template_resultats_ligne = '
<tr class="resultats_ligne">
  <td class="resultats_candidat">%s%s</td>
  <td class="resultats_voix text-right">%s</td>
  <td class="resultats_tx text-right">%s</td>
</tr>';

    /**
     * Template du tableau de la participation
     *
     * @var string
     */
    protected $template_participation_table = '
<table class="table table-bordered table-condensed table-striped">
  <thead>
    <tr class="participation_titre">
      <th>Heure</th>
      <th class="text-center">Votants</th>
      <th class="text-center">%%</th>
    </tr>
  </thead>
  <tbody>%s
  </tbody>
</table>';

    /**
     * Template d'une ligne de participation
     *
     * @var string
     */
    protected $template_participation_ligne = '
<tr class="participations_ligne">
  <td class="participations_candidat">%s</td>
  <td class="participations_voix text-right">%s</td>
  <td class="participations_tx text-right">%s</td>
</tr>';


    /**
     * Template de la zone destiné à l'affichage du
     * graphique
     *
     * @var string
     */
    protected $template_canvas = '
        <div class="panel-body container-chart text-center">
            <canvas id="%s" %s %s></canvas>
        </div>';

    /**
     * Template du bloc d'affichage de la participation par entité
     *
     * @var string
     */
    protected $template_participation_entite = '
    <div class="box panel panel-%s participation-entite">
        <div class="panel-heading">
            %s
        </div>
        <div class="panel-body">
            Inscrits : %d
        </div>
        %s
        %s
    </div>';

    /**
     * Template du bloc d'affichage de la participation
     * du périmètre
     *
     * @var string
     */
    protected $template_participation_perimetre =
    '<div class="panel box panel-%s participation participation-du-perimetre">
        <div class="panel-heading">
            Participation globale
        </div>
        <div class="panel-body">
            Inscrits : %d
        </div>
        %s
        %s
    </div>';

    /**
     * Template du bloc d'affichage de comparaison de la participation
     *
     * @var string
     */
    protected $template_comparaison_participation =
    '<div class="panel box panel-%s participation comparaison-participation">
        <div class="panel-heading">
            Comparaison participations
        </div>
        <div class="panel-body">
            %s
            %s
    </div>';

    /**
     * Template du bloc d'affichage des résultats d'une entité
     *
     * @var string
     */
    protected $template_resultats_entite =
    '<div class="box panel panel-%s resultats-entite candidats-%d">
        <div class="panel-heading">
        %s
        </div>
        <div class="panel-body">
            Inscrits : %d /
            Votants : %d (%d %%)<br>
            Blancs : %d /
            Nuls : %d /
            Exprimés : %d
        </div>
        %s
        %s
    </div>';

    /**
     * Template du tableau pour l'affichage du nombre de siège
     *
     * @var string
     */
    protected $template_tableau_siege =
        '<tr>
            <td>
                Liste no %d : %s
            </td>
            <td align="right" style="background-color:%s" class="liste_lm2">
                %d sièges
            </td>
        </tr>';

    /**
     * Template d'affichage du bloc de la répartition
     * des sièges pour le conseil municipale
     * @var string
     */
    protected $template_sieges_municipal =
        '<div id="repartition_sieges_cm" class="panel panel-%s">
            <div class="panel-heading">
                Conseil Municipal
            </div>
            <table class="table table-condensed">
                %s
            </table>
            %s
        </div>';

    /**
     * Template d'affichage du bloc de la répartition
     * des sièges pour le conseil communautaire
     * @var string
     */
    protected $template_sieges_communautaire =
        '<div id="repartition_sieges_cc" class="panel panel-%s">
            <div class="panel-heading">
                Conseil Communautaire
            </div>
            <table class="table table-condensed">
                %s
            </table>
            %s
        </div>';

    /**
     * Template d'affichage du bloc de la répartition
     * des sièges pour le conseil metropolitain
     * @var string
     */
    protected $template_sieges_metropolitain =
        '<div id="repartition_sieges_cmep" class="panel panel-%s">
            <div class="panel-heading">
                Conseil Metropolitain
            </div>
            <table class="table table-condensed">
                %s
            </table>
            %s
        </div>';


    /**
     * Template du bloc d'affichage des résultats du périmètre
     *
     * @var string
     */
    protected $template_resultats_perimetre = '
    <div class="box panel panel-%s resultats resultats-du-perimetre candidats-%d">
        <div class="panel-heading">
        RÉSULTATS GLOBAUX
        </div>
        <div class="panel-body">
            Total inscrits : %d <br>
            <br>
            <b>Cumul des unités arrivées</b><br>
            Inscrits : %d /
            Votants : %d (%d %%)<br>
            Blancs : %d /
            Nuls : %d /
            Exprimés : %d
        </div>
        %s
        %s
    </div>';
}
