Create New Item
Item Type
File
Folder
Item Name
Search file in folder and subfolders...
Are you sure want to rename?
File Manager
/
MassageV3
/
eliot
/
import_export
:
graphique0021.php
Advanced Search
Upload
New Item
Settings
Back
Back Up
Advanced Editor
Save
<?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>