File "graphique0021.php"

Full Path: /home/analogde/www/MassageV3/eliot/import_export/graphique0021.php
File size: 35.92 KB
MIME-type: text/x-php
Charset: utf-8

<?php
if (isset($_POST['data'])) {
    $jsonData = $_POST['data'];
    $tableData = json_decode($jsonData, true);
    $jsonData = json_encode($tableData);
}
?>
<!DOCTYPE html>
<html lang="fr">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Improve courbe planning</title>
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
    <link href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-zoom@latest"></script>

    <style>
        .back-button {
            position: absolute;
            top: 10px;
            left: 10px;
            padding: 10px 20px;
            font-size: 16px;
            background-color: #007bff;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
        }
        .back-button:hover {
            background-color: #0056b3;
        }
        .chart-title {
            text-align: center;
            margin-bottom: 20px;
            font-size: 1.5em;
            font-weight: bold;
        }
        #chart-container {
            width: 95vw;
            height: 100vh;
            display: flex;
            flex-direction: column;
            justify-content: center;
            align-items: center;
        }
        #myChart {
            width: 100% !important;
            height: 100% !important;
        }

        #burnDownChart {
            width: 100%; /* Largeur du canvas */
            height: 100%; /* Hauteur du canvas */
        }

    </style>

    <script>

/********************************************************************************************************/

    function getEasterDate(year)
    {
        const f = Math.floor,
        G = year % 19,
        C = f(year / 100),
        H = (C - f(C / 4) - f((8 * C + 13) / 25) + 19 * G + 15) % 30,
        I = H - f(H / 28) * (1 - f(29 / (H + 1)) * f((21 - G) / 11)),
        J = (year + f(year / 4) + I + 2 - C + f(C / 4)) % 7,
        L = I - J;
        const month = 3 + f((L + 40) / 44);
        const day = L + 28 - 31 * f(month / 4);
        return new Date(year, month - 1, day);
    }

/********************************************************************************************************/

    function generateRandomStrings(count = 10, length = 12)
    {
        const characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
        const strings = [];

        for (let i = 0; i < count; i++)
        {
        let randomString = '';
        for (let j = 0; j < length; j++) {
            const randomIndex = Math.floor(Math.random() * characters.length);
            randomString += characters[randomIndex];
        }
        strings.push(randomString);
    }

    return strings;
    }

/********************************************************************************************************/

    function getFrenchHolidays(year)
    {
        const easter = getEasterDate(year);
        const addDays = (date, days) => new Date(date.getFullYear(), date.getMonth(), date.getDate() + days);

        return [
            new Date(year, 0, 1),    // Jour de l'an
            new Date(year, 4, 1),    // Fête du Travail
            new Date(year, 4, 8),    // Victoire 1945
            new Date(year, 6, 14),   // Fête Nationale
            new Date(year, 7, 15),   // Assomption
            new Date(year, 10, 1),   // Toussaint
            new Date(year, 10, 11),  // Armistice
            new Date(year, 11, 25),  // Noël
            easter,                  // Pâques
            addDays(easter, 1),      // Lundi de Pâques
            addDays(easter, 39),     // Ascension
            addDays(easter, 49),     // Pentecôte
            addDays(easter, 50),     // Lundi de Pentecôte
        ];
    }

/********************************************************************************************************/

    function isWeekend(date)
    {
        const day = date.getDay();
        return day === 0 || day === 6;
    }

    function isHoliday(date, holidays)
    {
        return holidays.some(holiday =>
            date.getDate() === holiday.getDate() &&
            date.getMonth() === holiday.getMonth() &&
            date.getFullYear() === holiday.getFullYear()
        );
    }

/********************************************************************************************************/

    function countWorkingDays(startDate, endDate)
    {
            alert("TRACE");

            let count = 0;
            const current = new Date(startDate);
            const holidays = [];

            // collect holidays for all years involved
            for (let y = startDate.getFullYear(); y <= endDate.getFullYear(); y++) {
                holidays.push(...getFrenchHolidays(y));
            }

            while (current <= endDate) {
                if (!isWeekend(current) && !isHoliday(current, holidays)) {
                    count++;
                }
                current.setDate(current.getDate() + 1);
            }

        return count;
    }

/********************************************************************************************************/

    function addWorkingDays(startDate, workingDaysToAdd)
    {
        let addedDays = 0;
        const current = new Date(startDate);
        const holidays = [];

        // On prépare les jours fériés pour 5 ans autour de la date de départ
        const startYear = startDate.getFullYear();
        for (let y = startYear - 1; y <= startYear + 5; y++) {
            holidays.push(...getFrenchHolidays(y));
        }

        while (addedDays < workingDaysToAdd) {
            current.setDate(current.getDate() + 1);

            if (!isWeekend(current) && !isHoliday(current, holidays)) {
                addedDays++;
            }
        }

        return current;
    }

/********************************************************************************************************/

        function toto()
        {
            // passage du tableau
            var tableData = <?php echo $jsonData; ?>;
            var x_temps_passe = [];
            var x_temps_estimation = [];
            var taches = [];
            var plages = [];
            var tmp = [];
            var compteur_taches = 0;

            tableData.forEach(function(subArray)
            {
                if (subArray.id.includes("standard"))
                {
                    compteur_taches = compteur_taches + 1;
                }
            });

            console.log(" Nombre de points " + compteur_taches);

            tableData.forEach(function(subArray)
            {
                if (subArray.id.includes("standard"))
                {
                    var stockage = [];

                    x_temps_passe.push(subArray.count);
                    taches.push(subArray.name);

                    if (subArray.cells && typeof subArray.cells === 'object')
                    {
                             console.log(`Contenu des éléments dans 'cells' pour la tâche '${subArray.name}' :`);

                            // Parcourir chaque clé de "cells"
                            Object.keys(subArray.cells).forEach(key =>
                            {
                                const value = subArray.cells[key];

                                if (typeof value === 'object')
                                {
                                    //console.log(` 222  Clé '${key}' (Objet):`, JSON.stringify(value, null, 2));
                                    var flag = 0;

                                    for (const [prop, val] of Object.entries(value))
                                    {
                                        if (prop === 'value' && val === "1")
                                        {
                                            flag = 1;
                                            tmp.push(compteur_taches);
                                        }

                                        else if (prop === 'full_date' && flag === 1)
                                        {
                                            stockage.push(val);
                                            flag = 0;
                                        }
                                    }
                                }
                            });
                   }

                    console.log(" PLAGE                  " + stockage);
                    plages.push(stockage);
                    compteur_taches = compteur_taches - 1;
                }

                else if (subArray.id.includes("estimation"))
                {
                    x_temps_estimation.push(subArray.estimationValue);
                }
            });

            console.log("Plages sauvegardées : ", plages);
            console.log(" ZZZZZZZZ : ", tmp + " " + tmp.length);

/******* création des infos : durée ...  **********/

            // Créez un tableau pour stocker les premiers et derniers éléments
            var premiersEtDerniers = [];

            premiersEtDerniers.push(["", ""]);

            for (var i = 0; i < plages.length; i++)
            {
                var sousTableau = plages[i];
                if (sousTableau.length === 0)
                {
                    premiersEtDerniers.push([null, null]); // Ajoute [null, null] si le sous-tableau est vide
                }
                else
                {
                    premiersEtDerniers.push([sousTableau[0], sousTableau[sousTableau.length - 1]]);
                }
            }

            console.log(premiersEtDerniers);
            console.log(taches + " nombre " + taches.length);

            x_temps_passe.unshift("0");
            x_temps_estimation.unshift("0");

            x_temps_passe = x_temps_passe.map(Number);
            for (var i = 2; i < x_temps_passe.length; i++)
            {
                x_temps_passe[i] += x_temps_passe[i - 1];
            }

            x_temps_estimation = x_temps_estimation.map(Number);
            for (var i = 2; i < x_temps_estimation.length; i++)
            {
                x_temps_estimation[i] += x_temps_estimation[i - 1];
            }

            var gap_array = [];
            for (var i = 0; i < x_temps_estimation.length; i++)
            {
                let gap = (-1) * (x_temps_passe[i] - x_temps_estimation[i]);
                gap_array.push(gap);
            }

/*****************/

            var y = [];

            // generation des valeurs y
            for ( i = taches.length ; i >= 0; i--)
            {
                y.push(i);
            }

           // const y = [ 7, 6, 5, 4, 3, 2, 1, 0 ];

            console.log(" Passé " + x_temps_passe );
            console.log(" Estimation " + x_temps_estimation );
            console.log(" axe Y " + y );
            console.log(" cretin .. " + gap_array);
            console.log(" Nb taches .. " + taches.length);

            draw_chart(x_temps_passe, x_temps_estimation, y, gap_array, taches, premiersEtDerniers);

            draw_other(tmp, x_temps_passe, x_temps_estimation, 120, taches.length , taches , y);
        }
/********************************************************************************************************/

        function draw_other(tmp, x_temps_passe, x_temps_estimation, totalDays, totalTasks, taskLabels, y)
        {
            var array_repetition = [];

            console.log(" Local Passé " + x_temps_passe);
            console.log(" Local Estimation " + x_temps_estimation);

            let dernierElement_temps_passe = x_temps_passe[x_temps_passe.length - 1];
            let dernierElement_estimation = x_temps_estimation[x_temps_estimation.length - 1];

            let maxValue = Math.max(dernierElement_temps_passe, dernierElement_estimation);
            console.log("La plus grande valeur est : " + maxValue);

            taskLabels.reverse();
            taskLabels.unshift('');

            y.pop(); // supprime le dernier element
            console.log(" zorro " + y);

            x_temps_estimation.shift();
            console.log(" Bla " + x_temps_estimation);

            for (let i = 0; i < x_temps_estimation.length; i++) {
                if (i === 0) {
                    array_repetition.push(x_temps_estimation[0]);
                } else {
                    array_repetition.push(x_temps_estimation[i] - x_temps_estimation[i - 1]);
                }
            }

            console.log(" Tableau répetition " + array_repetition);
            // 10,15,29,24,10,12,12

            var ensemble = [];

            for (let i = 0; i < array_repetition.length; i++) {
                var loop = array_repetition[i];
                for (let j = 0; j < loop; j++) {
                    ensemble.push(y[i]);
                }
            }

            console.log(" ****** " + ensemble);

            /****** courbe 1 *********/

            let xyCouples_passe = [];

            // Générer les couples (x, y)
            for (let i = 0; i < tmp.length; i++) {
                let x = i + 1; // Valeur de x (jours)
                let y = tmp[i]; // Valeur de y (tâches restantes)
                xyCouples_passe.push({ x: x, y: y });
            }

            // Afficher les couples (x, y) dans la console
            //console.log("Couples (x, y) passé :", xyCouples);

            for (let i = 1; i < xyCouples_passe.length; i++) {
                if (xyCouples_passe[i].y === xyCouples_passe[i - 1].y - 1) {
                    const newPoint = { x: xyCouples_passe[i - 1].x, y: xyCouples_passe[i].y };
                    xyCouples_passe.splice(i, 0, newPoint);
                    i++; // Skip the newly inserted point in the next iteration
                }
            }

            console.log("Changed (x, y) passé :", xyCouples_passe);

            var temps_passe_step = [];

            for (let i = 1; i < xyCouples_passe.length; i++)
            {
                    if (xyCouples_passe[i - 1].x === xyCouples_passe[i].x) 
                    {
                        console.log(" Find : " + xyCouples_passe[i].x);
                        temps_passe_step.push(xyCouples_passe[i].x);
                    }
            }    

            temps_passe_step.push( dernierElement_temps_passe);

            console.log(" X passe transition :", temps_passe_step);


            
            var temps_passe_diff = [];

            [7, 24, 50, 69, 79, 90, 112]

            for (let i = 0; i < temps_passe_step.length; i++)
            {
                if( i === 0)
                {
                    temps_passe_diff.push(temps_passe_step[i]);
                }
                else
                {
                    var substracte =  temps_passe_step[i] - temps_passe_step[i-1]
                    temps_passe_diff.push( temps_passe_step[i] - temps_passe_step[i-1] );
                }   
                
            }    

            temps_passe_diff = temps_passe_diff.map(Number);

            console.log(" BOOM 2 :", temps_passe_diff);


            /****** courbe 2 *********/

            let xyCouples_estimation = [];

            // Générer les couples (x, y)
            for (let i = 0; i < ensemble.length; i++) {
                let x = i + 1; // Valeur de x (jours)
                let y = ensemble[i]; // Valeur de y (tâches restantes)
                xyCouples_estimation.push({ x: x, y: y });
            }

            // Afficher les couples (x, y) dans la console
            //console.log("Couples (x, y) estimation :", xyCouples_estimation);

            // Afficher les couples (x, y) dans la page HTML
            //document.getElementById('xyCouplesDisplay').textContent = JSON.stringify(xyCouples, null, 2);

            for (let i = 1; i < xyCouples_estimation.length; i++) {
                if (xyCouples_estimation[i].y === xyCouples_estimation[i - 1].y - 1) {
                    const newPoint = { x: xyCouples_estimation[i - 1].x, y: xyCouples_estimation[i].y };
                    xyCouples_estimation.splice(i, 0, newPoint);
                    i++; // Skip the newly inserted point in the next iteration
                }
            }

            console.log("Changed estimation(x, y) :", xyCouples_estimation);

            var estimation_step = [];

            for (let i = 1; i < xyCouples_estimation.length; i++)
            {
                    if (xyCouples_estimation[i - 1].x === xyCouples_estimation[i].x) 
                    {
                        console.log(" Find : " + xyCouples_estimation[i].x);
                        estimation_step.push(xyCouples_estimation[i].x);
                    }
            }    

            estimation_step.push( dernierElement_estimation);

            console.log(" X estimation transition :", estimation_step);

            /**************************/
            // pour chaque courbes, il faut insérer un point au debut des tableaux de couples  [ 0, numero tache la plus grande]

            const p1 = { x: 0, y: y[0] };

            xyCouples_passe.unshift(p1);
            xyCouples_estimation.unshift(p1);

            /**************************/

            // Créer le graphique
            const ctx = document.getElementById('burnDownChart').getContext('2d');
            const burnDownChart = new Chart(ctx, {
                type: 'line',
                data: {
                    //labels: Array.from({ length: totalDays }, (_, i) => i + 1), // Étiquettes pour l'axe X (jours)
                    //labels: Array.from({ length: totalDays + 1 }, (_, i) => i), // Étiquettes pour l'axe X (jours)
                    labels: Array.from({ length: maxValue + 1 }, (_, i) => i), // Étiquettes pour l'axe X (jours)

                    datasets: [
                        {
                            label: 'Temps estimé',
                            data: xyCouples_passe,
                            borderColor: 'rgba(153, 192, 192, 1)',
                            borderWidth: 1,
                            fill: false
                            //stepped: true // Ajouter cette option pour créer une courbe en escalier
                        },
                        {
                            label: 'Temps passé',
                            data: xyCouples_estimation,
                            borderColor: 'rgba(75, 102, 255, 1)',
                            borderWidth: 1,
                            fill: false
                        }
                    ]
                },
                options: {
                    scales: {
                        x: {
                            title: {
                                display: true,
                                text: 'Nombre de jours'
                            },
                            ticks: {
                                stepSize: 10 // Définissez le pas de la graduation de l'axe X à 10
                            }
                        },

                        // max ????

                        y: {
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: 'Tâches'
                            },
                            ticks: {
                                callback: function(value) {
                                    return taskLabels[value] || '';
                                },

                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {

                                title: function(context) {
                                    const xValue = context[0].parsed.x;
                                    return 'Jour ' + xValue;
                                },

                                label: function(context) 
                                {
                                    const label = context.dataset.label || '';
                                    const value = context.raw.y;
                                    const taskName = taskLabels[value] || 'Tâche inconnue';
                                    
                                    const index = context.dataIndex;

                                    let lines = []; // Initialisez lines comme un tableau


                                    let tooltipText = `${label}: ${taskName}`;

                                    lines.push(`${label}: ${taskName}`);
                                    // Vérifier si xValue est défini et l'ajouter à l'infobulle
                                    if (context.raw.xValue !== undefined) 
                                    {
                                            var duree = -1;
                                            var position = -1;
                                          
                                            if (context.raw.savedDatasetIndex === 0) 
                                            {
                                                position = temps_passe_step.indexOf(context.raw.xValue);
                                                //console.log(" POSITION 0 " + position);    
                                                
                                                //console.log(" XXXXX " + context.raw.xValue);

                                                if( position === 0)
                                                {
                                                    duree = temps_passe_step[position]; 
                                                }  
                                                else
                                                {
                                                    duree = temps_passe_step[position] -  temps_passe_step[position-1];  
                                                }      
                                            }
                                            else if (context.raw.savedDatasetIndex === 1) 
                                            {
                                                position = estimation_step.indexOf(context.raw.xValue);
                                                //console.log(" POSITION 1" + position);    

                                                //console.log(" ZZZZZ " + context.raw.xValue);

                                                if( position === 0)
                                                {
                                                    duree = estimation_step[position]; 
                                                }  
                                                else
                                                {
                                                    duree = estimation_step[position] -  estimation_step[position-1];  
                                                }       
                                            }

                                            console.log(" :::::::::: " + duree);    

                                            //tooltipText += ` (Durée écoulée : ${duree})`;
                                            lines.push( ` (Durée écoulée : ${duree}) ` );
                                            //lines.push( ` xValue: ${context.raw.xValue} ` );
                                            // tooltipText += ` (xValue: ${context.raw.xValue})`;

                                    }

                                    if (context.raw.savedDatasetIndex !== undefined) 
                                    {
                                        if (context.raw.savedDatasetIndex === 0) 
                                        {
                                            tooltipText += `<br>(Courbe: Temps estimé)`;
                                            lines.push("Courbe: Temps estimé");
                                        } 
                                        else if (context.raw.savedDatasetIndex === 1) 
                                        {
                                            tooltipText += `<br>(Courbe: Temps passé)`;
                                            lines.push("Courbe: Temps passé");
                                        }
                                    }
                                    /*if (context.raw.showBidule) 
                                    {
                                        //var element = temps_passe_diff[index];

                                        //const index = fruits.indexOf("banane");


                                        //console.log(">>> " + index);
                                        //tooltipText += `${element}`;
                                        //tooltipText += '\nbidule';
                                    }*/
                                    //return tooltipText;
                                    return lines;
                                    //return `${label}: ${taskName}`;
                                }
                            }
                        }
                    }
                }
            });


            // Ajouter un écouteur d'événement pour suivre les mouvements de la souris sur le graphique
            ctx.canvas.addEventListener('mousemove', function(evt) 
            {
                    const activePoints = burnDownChart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true);
                    if (activePoints.length > 0) 
                    {
                        const xValue = activePoints[0].element.$context.raw.x;

                        const datasetIndex = activePoints[0].datasetIndex;

                        //const xValueInt = parseInt(xValue, 10); // Convertir xValue en entier

                        //if (isInArray(temps_passe_diff, xValueInt )) {
                        //    console.log("BINGO");
                        //    alert("444");
                        //}

                        //console.log(" +++ " + xValue);
            
                        if (temps_passe_step.includes(xValue)) 
                        {
                            console.log("BINGO temps_passe_step " + xValue + " " + temps_passe_step);
                
                            activePoints[0].element.$context.raw.xValue = xValue;
                            activePoints[0].element.$context.raw.savedDatasetIndex = datasetIndex;
                            // Ajouter une propriété personnalisée pour indiquer que "bidule" doit être affiché
                            activePoints[0].element.$context.raw.showBidule = true;
                            burnDownChart.update(); // Mettre à jour le graphique pour refléter les changements
                        } 
                        
                        if (estimation_step.includes(xValue)) 
                        {
                            console.log("BINGO estimation_step " + xValue + " " + estimation_step);

                            activePoints[0].element.$context.raw.xValue = xValue;
                            activePoints[0].element.$context.raw.savedDatasetIndex = datasetIndex;
                            // Ajouter une propriété personnalisée pour indiquer que "bidule" doit être affiché
                            activePoints[0].element.$context.raw.showBidule = true;
                            burnDownChart.update(); // Mettre à jour le graphique pour refléter les changements    
                        }

                        else 
                        {
                            delete activePoints[0].element.$context.raw.xValue;
                            // Supprimer la propriété personnalisée si elle existe
                            delete activePoints[0].element.$context.raw.showBidule;
                            // Supprimer savedDatasetIndex si elle existe
                            
                             delete activePoints[0].element.$context.raw.savedDatasetIndex;
                            burnDownChart.update(); // Mettre à jour le graphique pour refléter les changements
                            
                        }
                    }
            });

        }

/********************************************************************************************************/

function isInArray(array, value) {
    for (let i = 0; i < array.length; i++) {
        if (array[i] === value) {
            return true;
        }
    }
    return false;
}

        function draw_chart(x1, x2, y, gap_array, taskLabels, premiersEtDerniers)
        {
                let x1_diff = [];
                let x2_diff = [];

                taskLabels.reverse();
                taskLabels.unshift('');

                console.log(taskLabels);

                for (let i = 1; i < x1.length; i++) {
                    let res_X1 = x1[i] - x1[i - 1];
                    let res_X2 = x2[i] - x2[i - 1];
                    x1_diff.push(`Durée écoulé = ${res_X1}`);
                    x2_diff.push(`Durée écoulé = ${res_X2}`);
                }

                // Déterminez la valeur maximale pour l'axe X
                let maxXValue = Math.max(...x1, ...x2);

            const ctx = document.getElementById('myChart').getContext('2d');
            const myChart = new Chart(ctx, {
                type: 'line',
                data: {
                    datasets: [
                        {
                            label: 'Temps estimé',
                            data: x1.map((value, index) => ({ x: value, y: y[index] })),
                            borderColor: 'rgba(75, 192, 192, 1)',
                            borderWidth: 1,
                            fill: false,
                            showLine: true
                        },
                        {
                            label: 'Temps passé',
                            data: x2.map((value, index) => ({ x: value, y: y[index] })),
                            borderColor: 'rgba(153, 102, 255, 1)',
                            borderWidth: 1,
                            fill: false,
                            showLine: true
                        }
                    ]
                },
                options: {
                    scales: {
                        x: {
                            type: 'linear',
                            position: 'bottom',
                            title: {
                                display: true,
                                text: 'Nombre de jours'
                            },
                            max: maxXValue, // Définissez la valeur maximale pour l'axe X
                            ticks: {
                                stepSize: 2 // Définissez le pas de la graduation de l'axe X
                                }
                        },
                        y: {
                            beginAtZero: true,
                            title: {
                                display: true,
                                text: 'Tâches'
                            },
                            ticks: {
                                callback: function(value) {
                                    return taskLabels[value] || '';
                                }
                            }
                        }
                    },
                    plugins: {
                        tooltip: {
                            callbacks: {
                                title: function(context) {
                                    const xValue = context[0].parsed.x;
                                    return 'Jour ' + xValue;
                                },
                                label: function(context) {
                                    const label = context.dataset.label || '';
                                    const value = context.raw.y;
                                    const index = context.dataIndex;
                                    let diffInfo = '';

                                    if (context.datasetIndex === 0 && index > 0) {
                                        diffInfo = x1_diff[index - 1];
                                    } else if (context.datasetIndex === 1 && index > 0) {
                                        diffInfo = x2_diff[index - 1];
                                    }

                                    console.log("Victoire ...");

                                    const taskName = taskLabels[value] || 'Tâche inconnue';
                                    let start = premiersEtDerniers[index][0];
                                    let stop = premiersEtDerniers[index][1];

                                    let lines = [];

                                    if (index === 0) {
                                        lines = [`${label}`];
                                    } else {
                                        if (context.datasetIndex === 0) {
                                            lines = [`${label} : ${taskName}`];
                                        } else if (context.datasetIndex === 1) {
                                            let aaa = "Début : " + start;
                                            let bbb = "Fin : " + stop;
                                            //lines = [`${label} : ${taskName}`, `${start}`, `${stop}`];
                                            lines = [`${label} : ${taskName}`, `${aaa}`, `${bbb}`];
                                        }
                                    }

                                    if (diffInfo && index > 0) lines.push(diffInfo);

                                    if (context.datasetIndex === 1 && gap_array[index] !== undefined && index > 0) {
                                        const gap = gap_array[index];
                                        if (gap > 0) {
                                            lines.push(`perdu (retard) = ${gap} jour(s)`);
                                        } else if (gap < 0) {
                                            lines.push(`gagné (avance) = ${gap} jour(s)`);
                                        }
                                    }

                                    return lines;
                                }
                            }
                        }
                    }
                }
            });
}

/********************************************************************************************************/

        document.addEventListener('DOMContentLoaded', function()
        {
            toto();

            console.log("Version 20");

            document.getElementById('backButton').addEventListener('click', function() {
                sessionStorage.setItem('returnValue', 'rechargement');
                window.history.back();
            });
        });

/********************************************************************************************************/

    </script>
</head>
<body>
    <button id="backButton" class="back-button">Retour</button>
    <div class="chart-container">
        <div class="chart-title">Double : Improve graphique 2 courbes</div>
        <canvas id="myChart"></canvas>

        <canvas id="burnDownChart"></canvas>

        <div id="xyCouplesDisplay"></div>

    </div>
</body>
</html>