/**
* Template Name: Bootslander
* Template URL: https://bootstrapmade.com/bootslander-free-bootstrap-landing-page-template/
* Updated: Mar 17 2024 with Bootstrap v5.3.3
* Author: BootstrapMade.com
* License: https://bootstrapmade.com/license/
*/
const analyses = {
  steps: {
    2022: `
      <h3>2022 : Une année de progression générale</h3>
      <ul>
        <li><strong>Corentin :</strong> Pic impressionnant de 10 500 pas, le plus actif de l'année.</li>
        <li><strong>Anis :</strong> Progression régulière avec une constance remarquable.</li>
        <li><strong>Maya :</strong> Montée progressive culminant en fin d'année.</li>
      </ul>
      <p>Tous les utilisateurs montrent une augmentation continue de leur activité, avec Corentin en tête, suivi d'Anis et de Maya.</p>
    `,
    2023: `
      <h3>2023 : Analyse des habitudes de marche</h3>
      <ul>
        <li><strong>Anis :</strong> Domine l'année avec un pic de 11 500 pas en mars, mais baisse notable en été.</li>
        <li><strong>Corentin :</strong> Activité croissante dès février, mais baisse hivernale.</li>
        <li><strong>Maya :</strong> Rythme stable avec une hausse estivale due à ses jobs étudiants.</li>
        <li><strong>Amira :</strong> Moins active avec des données partielles, baisse notable en fin d'année.</li>
      </ul>
      <p>Des tendances saisonnières et des obligations personnelles influencent l'activité de marche.</p>
    `,
    2024: `
      <h3>2024 : Une année de comportements variés</h3>
      <ul>
        <li><strong>Corentin :</strong> Forte activité en décembre, dépassant les 10 000 pas.</li>
        <li><strong>Anis :</strong> Régularité tout au long de l'année avec des variations en fin d'année.</li>
        <li><strong>Maya :</strong> Baisse liée au stress des examens en fin d'année.</li>
        <li><strong>Amira :</strong> Activité faible, mais légèrement accrue en été.</li>
      </ul>
      <p>Des tendances saisonnières comme la baisse hivernale et le pic de décembre sont observées.</p>
    `,
  },
  distanceCalories: {
    2023: `
      <h3>2023 : Distance et calories</h3>
      <ul>
        <li><strong>Anis :</strong> Leader incontesté, atteignant un pic en mars avec 484 calories brûlées.</li>
        <li><strong>Corentin :</strong> Activité constante, avec une hausse estivale marquée.</li>
        <li><strong>Maya et Amira :</strong> Moins actives, mais hausse notable en fin d'année.</li>
      </ul>
      <p>Les tendances montrent des variations saisonnières avec des pics en été et en décembre.</p>
    `,
    2024: `
      <h3>2024 : Comparaison distance-calories</h3>
      <ul>
        <li><strong>Anis :</strong> Plus actif, avec 6,73 km parcourus et 484 calories brûlées en mai.</li>
        <li><strong>Corentin :</strong> Activité accrue en décembre, mais reste derrière Anis.</li>
        <li><strong>Maya et Amira :</strong> Activité moindre, avec une hausse en décembre liée aux fêtes.</li>
      </ul>
      <p>Les mois de faible activité varient selon les utilisateurs, sans tendance claire.</p>
    `,
  },
  calories: {
    2023: `
      <h3>2023 : Analyse des calories brûlées</h3>
      <ul>
        <li><strong>Anis :</strong> Pic de 500 calories brûlées en mars, régularité tout au long de l'année.</li>
        <li><strong>Corentin :</strong> Activité stable, légère baisse estivale.</li>
        <li><strong>Maya :</strong> Constance avec un pic à 110 calories en septembre.</li>
        <li><strong>Amira :</strong> Progression vers la fin d'année, pic à 100 calories en décembre.</li>
      </ul>
      <p>Une fin d'année plus active pour tout le monde.</p>
    `,
    2024: `
      <h3>2024 : Analyse des calories</h3>
      <ul>
        <li><strong>Anis :</strong> Leader incontesté avec un pic de 450 calories en mai.</li>
        <li><strong>Corentin :</strong> Efforts notables, pic à 300 calories en avril et décembre.</li>
        <li><strong>Maya :</strong> Activité régulière entre 100 et 145 calories par mois.</li>
        <li><strong>Amira :</strong> Plus sédentaire, mais pic exceptionnel de 150 calories en septembre.</li>
      </ul>
      <p>Les résultats reflètent des dynamiques variées entre les membres.</p>
    `,
  },
};
function updateAnalysis(visualization, year) {
  const container = document.getElementById("analysis-content-" + visualization);
  if (analyses[visualization] && analyses[visualization][year]) {
    container.innerHTML = analyses[visualization][year];
  } else {
    container.innerHTML = "<p>Analyse indisponible pour cette année.</p>";
  }
}

(function() {
  "use strict";

  /**
   * Easy selector helper function
   */
  const select = (el, all = false) => {
    el = el.trim()
    if (all) {
      return [...document.querySelectorAll(el)]
    } else {
      return document.querySelector(el)
    }
  }

  /**
   * Easy event listener function
   */
  const on = (type, el, listener, all = false) => {
    let selectEl = select(el, all)
    if (selectEl) {
      if (all) {
        selectEl.forEach(e => e.addEventListener(type, listener))
      } else {
        selectEl.addEventListener(type, listener)
      }
    }
  }

  /**
   * Easy on scroll event listener 
   */
  const onscroll = (el, listener) => {
    el.addEventListener('scroll', listener)
  }

  /**
   * Navbar links active state on scroll
   */
  let navbarlinks = select('#navbar .scrollto', true)
  const navbarlinksActive = () => {
    let position = window.scrollY + 200
    navbarlinks.forEach(navbarlink => {
      if (!navbarlink.hash) return
      let section = select(navbarlink.hash)
      if (!section) return
      if (position >= section.offsetTop && position <= (section.offsetTop + section.offsetHeight)) {
        navbarlink.classList.add('active')
      } else {
        navbarlink.classList.remove('active')
      }
    })
  }
  window.addEventListener('load', navbarlinksActive)
  onscroll(document, navbarlinksActive)

  /**
   * Scrolls to an element with header offset
   */
  const scrollto = (el) => {
    let header = select('#header')
    let offset = header.offsetHeight

    if (!header.classList.contains('header-scrolled')) {
      offset -= 20
    }

    let elementPos = select(el).offsetTop
    window.scrollTo({
      top: elementPos - offset,
      behavior: 'smooth'
    })
  }

  /**
   * Toggle .header-scrolled class to #header when page is scrolled
   */
  let selectHeader = select('#header')
  if (selectHeader) {
    const headerScrolled = () => {
      if (window.scrollY > 100) {
        selectHeader.classList.add('header-scrolled')
      } else {
        selectHeader.classList.remove('header-scrolled')
      }
    }
    window.addEventListener('load', headerScrolled)
    onscroll(document, headerScrolled)
  }

  /**
   * Back to top button
   */
  let backtotop = select('.back-to-top')
  if (backtotop) {
    const toggleBacktotop = () => {
      if (window.scrollY > 100) {
        backtotop.classList.add('active')
      } else {
        backtotop.classList.remove('active')
      }
    }
    window.addEventListener('load', toggleBacktotop)
    onscroll(document, toggleBacktotop)
  }

  /**
   * Mobile nav toggle
   */
  on('click', '.mobile-nav-toggle', function(e) {
    select('#navbar').classList.toggle('navbar-mobile')
    this.classList.toggle('bi-list')
    this.classList.toggle('bi-x')
  })

  /**
   * Mobile nav dropdowns activate
   */
  on('click', '.navbar .dropdown > a', function(e) {
    if (select('#navbar').classList.contains('navbar-mobile')) {
      e.preventDefault()
      this.nextElementSibling.classList.toggle('dropdown-active')
    }
  }, true)

  /**
   * Scrool with ofset on links with a class name .scrollto
   */
  on('click', '.scrollto', function(e) {
    if (select(this.hash)) {
      e.preventDefault()

      let navbar = select('#navbar')
      if (navbar.classList.contains('navbar-mobile')) {
        navbar.classList.remove('navbar-mobile')
        let navbarToggle = select('.mobile-nav-toggle')
        navbarToggle.classList.toggle('bi-list')
        navbarToggle.classList.toggle('bi-x')
      }
      scrollto(this.hash)
    }
  }, true)

  /**
   * Scroll with ofset on page load with hash links in the url
   */
  window.addEventListener('load', () => {
    if (window.location.hash) {
      if (select(window.location.hash)) {
        scrollto(window.location.hash)
      }
    }
  });

  /**
   * Preloader
   */
  let preloader = select('#preloader');
  if (preloader) {
    window.addEventListener('load', () => {
      preloader.remove()
    });
  }

  /**
   * Initiate glightbox
   */
  const glightbox = GLightbox({
    selector: '.glightbox'
  });

  /**
   * Initiate gallery lightbox 
   */
  const galleryLightbox = GLightbox({
    selector: '.gallery-lightbox'
  });

  /**
   * Testimonials slider
   */
  new Swiper('.testimonials-slider', {
    speed: 600,
    loop: true,
    autoplay: {
      delay: 5000,
      disableOnInteraction: false
    },
    slidesPerView: 'auto',
    pagination: {
      el: '.swiper-pagination',
      type: 'bullets',
      clickable: true
    }
  });

  /**
   * Animation on scroll
   */
  window.addEventListener('load', () => {
    AOS.init({
      duration: 1000,
      easing: 'ease-in-out',
      once: true,
      mirror: false
    })
  });

  /**
   * Initiate Pure Counter 
   */
  new PureCounter();

})();

function renderStepsVisualization() {
  fetch('../static/js/final_combined_with_all_data.json') // Chemin à adapter si nécessaire
      .then((response) => response.json())
      .then((data) => {
          const parseDate = d3.timeParse("%Y-%m-%d");
          const formatYear = d3.timeFormat("%Y");
          const formatMonth = d3.timeFormat("%Y-%m");
          const members = ["Corentin", "Maya", "Anis", "Amira"];

          data.forEach(d => d.date = parseDate(d.date));

          const margin = { top: 50, right: 230, bottom: 150, left: 70 };
          const width = 800 - margin.left - margin.right;
          const height = 500 - margin.top - margin.bottom;

          const svgContainer = d3.select("#steps-visualization")
              .append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom + 50); // +50 pour la légende

          // Ajout du titre
          svgContainer.append("text")
              .attr("x", (width + margin.left + margin.right) / 2.5 ) // Centré horizontalement
              .attr("y", 20) // Positionné en haut
              .attr("text-anchor", "middle")
              .style("font-size", "18px")
              .style("font-weight", "bold")
              .text("Comparaison des pas des utilisateurs");

          const svg = svgContainer.append("g")
              .attr("transform", `translate(${margin.left},${margin.top})`);

          const years = [2022, 2023, 2024];
          const stepsPrevYearBtn = document.getElementById("stepsPrevYear");
          const stepsNextYearBtn = document.getElementById("stepsNextYear");
          const stepsCurrentYearDisplay = document.getElementById("stepsCurrentYear");

          stepsPrevYearBtn.addEventListener("click", () => {
              const currentYearIndex = years.indexOf(parseInt(stepsCurrentYearDisplay.textContent));
              if (currentYearIndex > 0) {
                  const newYear = years[currentYearIndex - 1];
                  stepsCurrentYearDisplay.textContent = newYear;
                  updateVisualization(newYear);
                  updateAnalysis("steps", newYear);

                  stepsNextYearBtn.disabled = false;
                  if (currentYearIndex - 1 === 0) {
                      stepsPrevYearBtn.disabled = true;
                  }
              }
          });

          stepsNextYearBtn.addEventListener("click", () => {
              const currentYearIndex = years.indexOf(parseInt(stepsCurrentYearDisplay.textContent));
              if (currentYearIndex < years.length - 1) {
                  const newYear = years[currentYearIndex + 1];
                  stepsCurrentYearDisplay.textContent = newYear;
                  updateVisualization(newYear);
                  updateAnalysis("steps", newYear);
                  stepsPrevYearBtn.disabled = false;
                  if (currentYearIndex + 1 === years.length - 1) {
                      stepsNextYearBtn.disabled = true;
                  }
              }
          });

          stepsPrevYearBtn.disabled = years.indexOf(parseInt(stepsCurrentYearDisplay.textContent)) === 0;
          stepsNextYearBtn.disabled = years.indexOf(parseInt(stepsCurrentYearDisplay.textContent)) === years.length - 1;

          updateVisualization(2024);

          function updateVisualization(selectedYear) {
              const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());

              if (filteredData.length === 0) {
                  console.log(`Aucune donnée pour l'année ${selectedYear}`);
                  return;
              }

              const groupedData = d3.groups(filteredData, d => formatMonth(d.date));

              const aggregatedData = groupedData.map(([month, records]) => {
                  const aggregated = { month };
                  members.forEach(member => {
                      aggregated[`Steps_${member}`] = d3.mean(records, d => d[`Steps_${member}`] || 0);
                  });
                  return aggregated;
              });

              svg.selectAll("*").remove();

              const xScale = d3.scaleBand()
                  .domain(aggregatedData.map(d => d.month))
                  .range([0, width])
                  .padding(0.2)
                  

              const yScale = d3.scaleLinear()
                  .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Steps_${member}`])))]).nice()
                  .range([height, 0]);

              const colorMap = {
                  "Maya": "#0f7e06",
                  "Corentin": "#1d38e3",
                  "Anis": "#d6bff4",
                  "Amira": "#7e09bd"
              };

              svg.append("g")
                  .attr("transform", `translate(0, ${height})`)
                  .call(d3.axisBottom(xScale))
                  .selectAll("text")
                  .attr("transform", "rotate(-45)")
                  .style("text-anchor", "end");

              svg.append("g").call(d3.axisLeft(yScale));

              svg.append("text")
                  .attr("x", width / 2)
                  .attr("y", height + 70)
                  .attr("text-anchor", "middle")
                  .style("font-size", "14px")
                  .text("Mois");

              svg.append("text")
                  .attr("transform", "rotate(-90)")
                  .attr("x", -height / 2)
                  .attr("y", -50)
                  .attr("text-anchor", "middle")
                  .style("font-size", "14px")
                  .text("Nombre de pas");

              members.forEach((member) => {
                  const lineData = aggregatedData.map(d => {
                      let steps = d[`Steps_${member}`] === -1.0 ? 0 : d[`Steps_${member}`];
                      return { month: d.month, steps };
                  });

                  const line = d3.line()
                      .x(d => xScale(d.month) + xScale.bandwidth() / 2)
                      .y(d => yScale(d.steps))
                      .defined(d => d.steps !== 0);

                  svg.append("path")
                      .data([lineData])
                      .attr("class", `line-${member}`)
                      .attr("d", line)
                      .attr("fill", "none")
                      .attr("stroke", colorMap[member])
                      .attr("stroke-width", 2);
              });

              const legend = svg.append("g")
                  .attr("transform", `translate(${width / 20}, ${height + 80})`);

              members.forEach((member, i) => {
                  const legendGroup = legend.append("g")
                      .attr("transform", `translate(${i * 150}, 0)`);

                  legendGroup.append("rect")
                      .attr("width", 15)
                      .attr("height", 15)
                      .attr("fill", colorMap[member]);

                  legendGroup.append("text")
                      .attr("x", 20)
                      .attr("y", 12)
                      .style("font-size", "12px")
                      .text(member);
              });
          }
      });
}





// VISU 2
function renderDistanceVisualization() {
  fetch('../static/js/final_combined_with_all_data.json') // Chemin à adapter si nécessaire
      .then((response) => response.json())
      .then((data) => {
          const parseDate = d3.timeParse("%Y-%m-%d");
          const formatYear = d3.timeFormat("%Y");
          const formatMonth = d3.timeFormat("%Y-%m");
          const members = ["Corentin", "Maya", "Anis", "Amira"];

          data.forEach(d => d.date = parseDate(d.date));

          const margin = { top: 50, right: 230, bottom: 150, left: 70 };
          const width = 800 - margin.left - margin.right;
          const height = 500 - margin.top - margin.bottom;

          const svg = d3.select("#distance-visualization")
              .append("svg")
              .attr("width", width + margin.left + margin.right)
              .attr("height", height + margin.top + margin.bottom)
              .append("g")
              .attr("transform", `translate(${margin.left},${margin.top})`);

          const years = [2023, 2024];
          const prevYearBtn = document.getElementById("distancePrevYear");
const nextYearBtn = document.getElementById("distanceNextYear");
const currentYearDisplay = document.getElementById("distanceCurrentYear");

// Gestion des événements des boutons
prevYearBtn.addEventListener("click", () => {
    const currentYearIndex = years.indexOf(parseInt(currentYearDisplay.textContent));
    if (currentYearIndex > 0) {
        const newYear = years[currentYearIndex - 1];
        currentYearDisplay.textContent = newYear;
        updateVisualization(newYear);
        updateAnalysis("distanceCalories", newYear);

        // Activer/désactiver les boutons
        nextYearBtn.disabled = false;
        if (currentYearIndex - 1 === 0) {
            prevYearBtn.disabled = true;
        }
    }
});

nextYearBtn.addEventListener("click", () => {
    const currentYearIndex = years.indexOf(parseInt(currentYearDisplay.textContent));
    if (currentYearIndex < years.length - 1) {
        const newYear = years[currentYearIndex + 1];
        currentYearDisplay.textContent = newYear;
        updateVisualization(newYear);
        updateAnalysis("distanceCalories", newYear);

        // Activer/désactiver les boutons
        prevYearBtn.disabled = false;
        if (currentYearIndex + 1 === years.length - 1) {
            nextYearBtn.disabled = true;
        }
    }
});

// Initialisation des boutons
prevYearBtn.disabled = years.indexOf(parseInt(currentYearDisplay.textContent)) === 0;
nextYearBtn.disabled = years.indexOf(parseInt(currentYearDisplay.textContent)) === years.length - 1;


          

          const tooltip = d3.select("body").append("div")
              .attr("class", "tooltip-distance")
              .style("opacity", 0);

          function updateVisualization(selectedYear) {
              const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());
              const groupedData = d3.groups(filteredData, d => formatMonth(d.date));

              const colorMap = {
                  "Maya": "#0f7e06",
                  "Corentin": "#1d38e3",
                  "Anis": "#d6bff4",
                  "Amira": "#7e09bd"
              };

              const aggregatedData = groupedData.map(([month, records]) => {
                  const aggregated = { month };
                  members.forEach(member => {
                      aggregated[`Distance_${member}`] = d3.mean(records, d => {
                          const distance = d[`Distance_${member}`];
                          return (distance !== -1) ? distance : undefined;
                      }) || 0;

                      aggregated[`Calories_${member}`] = d3.mean(records, d => {
                          const calories = d[`Calories_${member}`];
                          return (calories !== -1) ? calories : undefined;
                      }) || 0;
                  });
                  return aggregated;
              });

              svg.selectAll("*").remove();

              const bubbleSizeScale = d3.scaleLinear()
                  .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Distance_${member}`])) )])
                  .range([2, 20]);

              const xScale = d3.scaleLinear()
                  .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Distance_${member}`])) )])
                  .range([0, width]);

              const yScale = d3.scaleLinear()
                  .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Calories_${member}`])) )])
                  .range([height, 0]);

              svg.append("text")
                  .attr("x", width / 2)
                  .attr("y", margin.top - 75)
                  .attr("text-anchor", "middle")
                  .style("font-size", "16px")
                  .style("font-weight", "bold")
                  .text("Comparaison des calories brûlées vs distance parcourue");

              svg.append("g")
                  .attr("transform", `translate(0, ${height})`)
                  .call(d3.axisBottom(xScale));

              svg.append("text")
                  .attr("x", width / 2)
                  .attr("y", height + 70)
                  .attr("text-anchor", "middle")
                  .style("font-size", "14px")
                  .text("Distance (KM)");

              svg.append("g").call(d3.axisLeft(yScale));

              svg.append("text")
                  .attr("transform", "rotate(-90)")
                  .attr("x", -height / 2)
                  .attr("y", -50)
                  .attr("text-anchor", "middle")
                  .style("font-size", "14px")
                  .text("Calories brûlées");

              members.forEach((member) => {
                  svg.selectAll(`.bubble-${member}`)
                      .data(aggregatedData)
                      .enter()
                      .append("circle")
                      .attr("cx", d => xScale(d[`Distance_${member}`]))
                      .attr("cy", d => yScale(d[`Calories_${member}`]))
                      .attr("r", d => 0.8*  bubbleSizeScale(d[`Distance_${member}`]))
                      .attr("fill", d => {
                          return (d[`Distance_${member}`] === 0 || d[`Calories_${member}`] === 0) ? "gray" : colorMap[member];
                      })
                      .style("opacity", 0.7)
                      .on("mouseover", function(event, d) {
    tooltip.transition().duration(200).style("opacity", 0.9);
    const monthFormatted = d3.timeFormat("%B")(parseDate(d.month)); // Formatage du mois
    const distance = d[`Distance_${member}`] ? d[`Distance_${member}`].toFixed(2) : "Pas de données";
    const calories = d[`Calories_${member}`] ? d[`Calories_${member}`].toFixed(2) : "Pas de données";

    tooltip.html(`
        <strong>${member}</strong><br>
        Mois : ${d.month}<br>
        Distance : ${distance} km<br>
        Calories : ${calories} cal
    `)
    .style("left", `${event.pageX + 10}px`)
    .style("top", `${event.pageY - 28}px`);
})
.on("mousemove", function(event) {
    tooltip.style("left", `${event.pageX + 10}px`).style("top", `${event.pageY - 28}px`);
})
.on("mouseout", function() {
    tooltip.transition().duration(500).style("opacity", 0);
});
// Ajouter une légende horizontale sous le graphique
const legend = svg.append("g")
    .attr("transform", `translate(${width / 2 - (members.length * 110) / 2}, ${height + 90})`); // Positionnement horizontal centré

members.forEach((member, i) => {
    const legendGroup = legend.append("g")
        .attr("transform", `translate(${i * 100}, 0)`); // Espacement horizontal entre les éléments

    // Rectangle coloré pour la légende
    legendGroup.append("rect")
        .attr("width", 15)
        .attr("height", 15)
        .attr("fill", colorMap[member])
        .style("opacity", 0.8);

    // Texte descriptif à côté du rectangle
    legendGroup.append("text")
        .attr("x", 20) // Décalage horizontal par rapport au rectangle
        .attr("y", 12) // Alignement vertical au centre
        .style("font-size", "12px")
        .text(member);
});
              });
          }

          updateVisualization(years[1]);

          
      });
}

//VISU 3
function renderCaloriesVisualization() {
  fetch('../static/js/final_combined_with_all_data.json')
    .then((response) => response.json())
    .then((data) => {
      const parseDate = d3.timeParse("%Y-%m-%d");
      const formatYear = d3.timeFormat("%Y");
      const formatMonth = d3.timeFormat("%Y-%m");
      const members = ["Corentin", "Maya", "Anis", "Amira"];

      data.forEach(d => d.date = parseDate(d.date));

      const margin = { top: 50, right: 230, bottom: 150, left: 70 };
      const width = 800 - margin.left - margin.right;
      const height = 500 - margin.top - margin.bottom;

      const svg = d3.select("#calories-visualization")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`);

      const years = [2022, 2023, 2024];
      const prevYearBtn = document.getElementById("caloriesPrevYear");
const nextYearBtn = document.getElementById("caloriesNextYear");
const currentYearDisplay = document.getElementById("caloriesCurrentYear");

// Gestion des événements des boutons
prevYearBtn.addEventListener("click", () => {
    const currentYearIndex = years.indexOf(parseInt(currentYearDisplay.textContent));
    if (currentYearIndex > 0) {
        const newYear = years[currentYearIndex - 1];
        currentYearDisplay.textContent = newYear;
        updateVisualization(newYear);
        updateAnalysis("calories", newYear);
        // Activer/désactiver les boutons
        nextYearBtn.disabled = false;
        if (currentYearIndex - 1 === 0) {
            prevYearBtn.disabled = true;
        }
    }
});

nextYearBtn.addEventListener("click", () => {
    const currentYearIndex = years.indexOf(parseInt(currentYearDisplay.textContent));
    if (currentYearIndex < years.length - 1) {
        const newYear = years[currentYearIndex + 1];
        currentYearDisplay.textContent = newYear;
        updateVisualization(newYear);
        updateAnalysis("calories", newYear);

        // Activer/désactiver les boutons
        prevYearBtn.disabled = false;
        if (currentYearIndex + 1 === years.length - 1) {
            nextYearBtn.disabled = true;
        }
    }
});

// Initialisation des boutons
prevYearBtn.disabled = years.indexOf(parseInt(currentYearDisplay.textContent)) === 0;
nextYearBtn.disabled = years.indexOf(parseInt(currentYearDisplay.textContent)) === years.length - 1;

      updateVisualization(2024);

      function updateVisualization(selectedYear) {
        const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());

        if (filteredData.length === 0) {
          console.log(`Aucune donnée pour l'année ${selectedYear}`);
          return;
        }

        const groupedData = d3.groups(filteredData, d => formatMonth(d.date));

        const aggregatedData = groupedData.map(([month, records]) => {
          const aggregated = { month };
          members.forEach(member => {
            aggregated[`Calories_${member}`] = d3.mean(records, d => d[`Calories_${member}`] || 0);
            
          });
          return aggregated;
        });

        svg.selectAll("*").remove();

        svg.append("text")
          .attr("x", width / 2)
          .attr("y", margin.top - 60)
          .attr("text-anchor", "middle")
          .style("font-size", "16px")
          .style("font-weight", "bold")
          .text("Analyse des calories brûlées par mois");

        const xScale = d3.scaleBand()
          .domain(aggregatedData.map(d => d.month))
          .range([0, width])
          .padding(0.2);

        const yScale = d3.scaleLinear()
          .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Calories_${member}`])))]).nice()
          .range([height, 0]);

        const colorScale = d3.scaleOrdinal()
          .domain(members)
          .range(["#1d38e3", "#0f7e06", "#d6bff4", "#7e09bd"]);

        svg.append("g")
          .attr("transform", `translate(0, ${height})`)
          .call(d3.axisBottom(xScale))
          .selectAll("text")
          .attr("transform", "rotate(-45)")
          .style("text-anchor", "end");

        svg.append("text")
          .attr("x", width / 2)
          .attr("y", height + 70)
          .attr("text-anchor", "middle")
          .style("font-size", "14px")
          .text("Mois");

        svg.append("g").call(d3.axisLeft(yScale));

        svg.append("text")
          .attr("transform", "rotate(-90)")
          .attr("x", -height / 2)
          .attr("y", -50)
          .attr("text-anchor", "middle")
          .style("font-size", "14px")
          .text("Calories brûlées");
        // Ajout de la légende
const legend = svg.append("g")
.attr("transform", `translate(${width / 2 - (members.length * 120) / 2}, ${height + 100})`); // Positionnement

members.forEach((member, i) => {
const legendGroup = legend.append("g")
    .attr("transform", `translate(${i * 120}, 0)`); // Espacement horizontal

// Rectangle coloré
legendGroup.append("rect")
    .attr("width", 15)
    .attr("height", 15)
    .attr("fill", colorScale(member))
    .style("opacity", 0.8);

// Texte descriptif
legendGroup.append("text")
    .attr("x", 20) // Position par rapport au rectangle
    .attr("y", 12) // Alignement vertical
    .style("font-size", "12px")
    .text(member);
});


        members.forEach(member => {
          const areaData = aggregatedData.map(d => ({
            month: d.month,
            calories: d[`Calories_${member}`] || 0
          }));

          const area = d3.area()
            .x(d => xScale(d.month) + xScale.bandwidth() / 2)
            .y0(yScale(0.8))
            .y1(d => yScale(d.calories ));

          svg.append("path")
            .data([areaData])
            .attr("fill", colorScale(member))
            .attr("opacity", 0.8)
            .attr("d", area);
        });
      }

    });
}

// Visu4
function renderSleepVisualization() {
  fetch('../static/js/final_combined_with_all_data.json') // Adapter le chemin si nécessaire
  .then((response) => response.json())
  .then((data) => {
      const parseDate = d3.timeParse("%Y-%m-%d");
      const formatYear = d3.timeFormat("%Y");
      const formatMonth = d3.timeFormat("%Y-%m");
      const formatDay = d3.timeFormat("%d");
      const members = ["Corentin", "Maya", "Anis", "Amira"];
      data.forEach(d => d.date = parseDate(d.date));

      // Dimensions et marges
      const margin = { top: 50, right: 230, bottom: 150, left: 70 };
      const width = 800 - margin.left - margin.right;
      const height = 500 - margin.top - margin.bottom;

      // Créer le conteneur SVG principal
      const svg = d3.select("#sleep-visualization")
          .append("svg")
          .attr("width", width + margin.left + margin.right)
          .attr("height", height + margin.top + margin.bottom)
          .append("g")
          .attr("transform", `translate(${margin.left},${margin.top})`);

      // Créer un conteneur pour le graphique détaillé
      const detailContainer = d3.select("#sleep-visualization")
          .append("div")
          .attr("id", "detail-container")
          .style("margin-top", "20px");

      // Définir les années et la plage d'affichage
      const years = [2021, 2022, 2023, 2024];
      

      // Créer le slider
      // Ajoutez les boutons Bootstrap pour naviguer entre les années



// Gestion des événements des boutons
let currentYearIndex = years.indexOf(2024); // Année initiale

// Fonction pour mettre à jour l'état des boutons
function updateButtonStates() {
    if (currentYearIndex <= 0) {
        document.getElementById("prevYear").style.display = "hidden"; // Cacher le bouton précédent
    } else {
        document.getElementById("prevYear").style.display = "inline-block"; // Réafficher le bouton précédent
    }

    if (currentYearIndex >= years.length - 1) {
        document.getElementById("nextYear").style.display = "hidden"; // Cacher le bouton suivant
    } else {
        document.getElementById("nextYear").style.display = "inline-block"; // Réafficher le bouton suivant
    }
}

// Initialiser l'état des boutons
updateButtonStates();

// Événement pour le bouton précédent
document.getElementById("prevYear").addEventListener("click", () => {
    if (currentYearIndex > 0) {
        currentYearIndex--;
        document.getElementById("currentYear").textContent = years[currentYearIndex];
        updateVisualization(years[currentYearIndex]);
        updateButtonStates(); // Mettre à jour l'état des boutons
    }
});

// Événement pour le bouton suivant
document.getElementById("nextYear").addEventListener("click", () => {
    if (currentYearIndex < years.length - 1) {
        currentYearIndex++;
        document.getElementById("currentYear").textContent = years[currentYearIndex];
        updateVisualization(years[currentYearIndex]);
        updateButtonStates(); // Mettre à jour l'état des boutons
    }
});

      // Tooltip
      const tooltip = d3.select("body").append("div")
          .attr("class", "tooltip-sleep")
          .style("opacity", 0);

      // Fonction de mise à jour de la visualisation
      function updateVisualization(selectedYear) {
          const filteredData = data.filter(d => formatYear(d.date) === selectedYear.toString());
          const groupedData = d3.groups(filteredData, d => formatMonth(d.date));

          const colorMap = {
              "Maya": "#0f7e06",
              "Corentin": "#1d38e3",
              "Anis": "#d6bff4",
              "Amira": "#7e09bd"
          };            

          const aggregatedData = groupedData.map(([month, records]) => {
              const aggregated = { month };
              members.forEach(member => {
                  aggregated[`Sleep_${member}`] = d3.mean(records, d => d[`Sleep_${member}`] || 0);
              });
              return aggregated;
          });

          svg.selectAll("*").remove();

          svg.append("text")
              .attr("x", width / 2)  // Centrer horizontalement
              .attr("y", margin.top - 60)  // Positionner légèrement au-dessus du graphique
              .attr("text-anchor", "middle")  // Centrer le texte
              .style("font-size", "16px")  // Taille de police
              .style("font-weight", "bold")  // Gras
              .text("Analyse des heures de sommeil par mois");

          const xScale = d3.scaleBand()
              .domain(aggregatedData.map(d => d.month))
              .range([0, width])
              .padding(0.2);

          const yScale = d3.scaleLinear()
              .domain([0, d3.max(aggregatedData, d => Math.max(...members.map(member => d[`Sleep_${member}`])))]).nice()
              .range([height, 0]);

          const colorScale = d3.scaleOrdinal(d3.schemeCategory10).domain(members);

          // Axe X
          svg.append("g")
              .attr("transform", `translate(0, ${height})`)
              .call(d3.axisBottom(xScale))
              .selectAll("text")
              .attr("transform", "rotate(-45)")
              .style("text-anchor", "end");

          // Légende de l'axe X
          svg.append("text")
              .attr("x", width / 2)
              .attr("y", height + 70)
              .attr("text-anchor", "middle")
              .style("font-size", "14px")
              .text("Mois");

          // Axe Y
          svg.append("g").call(d3.axisLeft(yScale));

          // Légende de l'axe Y
          svg.append("text")
              .attr("transform", "rotate(-90)")
              .attr("x", -height / 2)
              .attr("y", -50)
              .attr("text-anchor", "middle")
              .style("font-size", "14px")
              .text("Sommeil moyen (heures)");

          // Légende des membres (rectangles colorés)
          // Créer un conteneur pour la légende
const legend = svg.append("g")
.attr("transform", `translate(${width / 3}, ${height + margin.bottom - 50})`) // Positionner la légende en bas, centrée
.attr("text-anchor", "middle");

// Ajouter les éléments de la légende
members.forEach((member, i) => {
legend.append("rect")
    .attr("x", i * 100 - (members.length * 50)) // Espacement horizontal entre les rectangles
    .attr("y", 0)
    .attr("width", 15)
    .attr("height", 15)
    .attr("fill", colorMap[member]);

legend.append("text")
    .attr("x", i * 100 - (members.length * 50) + 20) // Texte à côté du rectangle
    .attr("y", 12)
    .text(member)
    .style("font-size", "12px")
    .attr("text-anchor", "start");
});

// Ajouter un élément pour "Pas de données"
legend.append("rect")
.attr("x", members.length * 100 - (members.length * 50)) // Position pour le rectangle gris
.attr("y", 0)
.attr("width", 15)
.attr("height", 15)
.attr("fill", "lightgrey");

legend.append("text")
.attr("x", members.length * 100 - (members.length * 50) + 20) // Texte à côté du rectangle gris
.attr("y", 12)
.text("Pas de données")
.style("font-size", "12px")
.attr("text-anchor", "start");

          // Barres pour chaque membre
          members.forEach((member, i) => {
              svg.selectAll(`.bar-sleep-${member}`)
                  .data(aggregatedData)
                  .enter()
                  .append("rect")
                  .attr("x", d => xScale(d.month) + i * (xScale.bandwidth() / members.length))
                  .attr("y", d => {
                      const value = d[`Sleep_${member}`];
                      return value === -1.0 ? yScale(2) : yScale(value); // Placer les -1.0 à une hauteur fixe, ici 2 heures
                  })
                  .attr("width", xScale.bandwidth() / members.length)
                  .attr("height", d => {
                      const value = d[`Sleep_${member}`];
                      return value === -1.0 ? height - yScale(2) : height - yScale(value); // Barres grisées si -1.0
                  })
                  .attr("fill", d => {
                      const value = d[`Sleep_${member}`];
                      return value === -1.0 ? "#D3D3D3" : colorMap[member]; // Gris pour -1.0
                  })
                  .on("mouseover", function(event, d) {
                      tooltip.transition().duration(200).style("opacity", .9); // Transition d'apparition du tooltip
                      tooltip.html(`Mois : ${d.month}<br>Sommeil moyen : ${d[`Sleep_${member}`] === -1.0 ? "Pas de données" : d[`Sleep_${member}`].toFixed(2)} heures`) // Affichage du tooltip
                          .style("left", (event.pageX + 5) + "px")
                          .style("top", (event.pageY - 28) + "px");
                  })
                  .on("mouseout", function() {
                      tooltip.transition().duration(500).style("opacity", 0); // Transition de disparition du tooltip
                  })
                  .on("click", (event, d) => {
                      const memberColor = colorMap[member]; // Récupérer la couleur du membre
                      showDetailChart(d.month, member, selectedYear, memberColor); // Passer la couleur à la fonction showDetailChart
                  });
          });
          
      }
      
     // Fonction pour afficher les détails
     function showDetailChart(month, member, year, memberColor) {
      // Affiche le modal
      const modal = d3.select("#modal");
      modal.style("display", "block");
  
      // Fermer le modal
      modal.select(".close").on("click", () => {
          modal.style("display", "none");
          d3.select("#detail-visualization").selectAll("*").remove();
      });
  
      const detailContainer = d3.select("#detail-visualization");
      detailContainer.selectAll("*").remove();
  
      const filteredData = data.filter(d => formatYear(d.date) === year.toString() && formatMonth(d.date) === month);
  
      const dailyData = d3.groups(filteredData, d => formatDay(d.date)).map(([day, records]) => ({
          day: day,
          value: d3.mean(records, d => d[`Sleep_${member}`] || 0)
      }));
  
      const detailSvg = detailContainer.append("svg")
          .attr("width", 600)
          .attr("height", 400)
          .append("g")
          .attr("transform", "translate(50, 50)");
  
      const xScale = d3.scaleBand()
          .domain(dailyData.map(d => d.day))
          .range([0, 500])
          .padding(0.1);
  
      const yScale = d3.scaleLinear()
          .domain([0, d3.max(dailyData, d => d.value)]).nice()
          .range([300, 0]);
  
      // Ajout de l'axe X
      detailSvg.append("g")
          .attr("transform", "translate(0, 300)")
          .call(d3.axisBottom(xScale));
  
      // Ajout de l'axe Y
      detailSvg.append("g")
          .call(d3.axisLeft(yScale));
  
      // Titre du graphique
      detailSvg.append("text")
          .attr("x", 250)
          .attr("y", -20)
          .attr("text-anchor", "middle")
          .style("font-size", "16px")
          .text(`${member} - Sommeil du mois de ${month} (${year})`);
  
      // Ajouter la légende de l'axe X (Jours)
      detailSvg.append("text")
          .attr("x", 250)
          .attr("y", 340)
          .attr("text-anchor", "middle")
          .style("font-size", "12px")
          .text("Jours du mois");
  
      // Ajouter la légende de l'axe Y (Heures de sommeil)
      detailSvg.append("text")
          .attr("transform", "rotate(-90)")
          .attr("x", -200)
          .attr("y", -40)
          .attr("text-anchor", "middle")
          .style("font-size", "12px")
          .text("Heures de sommeil moyen");
          

      // Dessin des barres
      detailSvg.selectAll(".bar")
          .data(dailyData)
          .enter()
          .append("rect")
          .attr("x", d => xScale(d.day))
          .attr("y", d => {
              const value = d.value;
              return value < 0 || value === null ? yScale(2) : yScale(value);
          })
          .attr("width", xScale.bandwidth())
          .attr("height", d => {
              const value = d.value;
              return value < 0 || value === null ? 300 - yScale(2) : 300 - yScale(value);
          })
          .attr("fill", d => {
              const value = d.value;
              return value < 0 || value === null ? "lightgrey" : memberColor;
          })
          .on("mouseover", function(event, d) {
            tooltip.transition().duration(200).style("opacity", 1);
            tooltip.html(`
                <div style="text-align: center;">
                  <strong>Jour :</strong> ${d.day}<br>
                  <strong>Sommeil :</strong> ${d.value === -1.0 || d.value === null ? "Pas de données" : d.value.toFixed(2)} heures
                </div>
            `);
        })
        .on("mousemove", function(event) {
            tooltip
                .style("left", (event.pageX + 15) + "px") // Décalage pour positionner le tooltip
                .style("top", (event.pageY + 15) + "px");
        })
        .on("mouseout", function() {
            tooltip.transition().duration(500).style("opacity", 0);
        });
        
  }
  


      // Initialisation de la visualisation
      updateVisualization(years[3]);

      // Mettre à jour la visualisation lorsque le slider est déplacé
      rangeSlider.on("input", function() {
          const selectedYear = years[this.value];
          yearDisplay.text(selectedYear);
          updateVisualization(selectedYear);
      });
      });
}




// Visu 5
function renderSleepActivityVisualization() {
  fetch('../static/js/final_combined_with_all_data.json') // Adapter le chemin si nécessaire
    .then(response => response.json())
    .then(data => {
      const svg = d3.select("#sleep-activity-visualization")
        .append("svg")
        .attr("width", 700)
        .attr("height", 300);

      const margin = { top: 20, right: 150, bottom: 50, left: 50 };
      const width = +svg.attr("width") - margin.left - margin.right;
      const height = +svg.attr("height") - margin.top - margin.bottom;

      const g = svg.append("g").attr("transform", `translate(${margin.left},${margin.top})`);

      const tooltip = d3.select("body").append("div")
        .attr("class", "tooltip")
        .style("position", "absolute")
        .style("visibility", "hidden")
        .style("background", "#fff")
        .style("border", "1px solid #ccc")
        .style("padding", "5px")
        .style("border-radius", "4px")
        .style("font-size", "12px");

      const colorMap = {
        "Maya": "#0f7e06",
        "Corentin": "#1d38e3",
        "Anis": "#d6bff4",
        "Amira": "#7e09bd"
      };

      const getISOWeekNumber = (date) => {
        const tempDate = new Date(date);
        tempDate.setHours(0, 0, 0, 0);
        tempDate.setDate(tempDate.getDate() + 4 - (tempDate.getDay() || 7));
        const yearStart = new Date(tempDate.getFullYear(), 0, 1);
        return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7);
      };

      const filteredData = data.filter(d => {
        const date = new Date(d.date);
        return date >= new Date("2023-10-01") && date <= new Date("2024-12-31");
      });

      const groupedData = d3.group(filteredData, d => {
        const date = new Date(d.date);
        const weekNumber = getISOWeekNumber(date);
        return `${date.getFullYear()}-W${weekNumber}`;
      });

      const processedData = Array.from(groupedData, ([week, records]) => {
        return records.map(d => ([
          { name: "Anis", steps: d.Steps_Anis, sleep: d.Sleep_Anis, calories: d.Calories_Anis },
          { name: "Maya", steps: d.Steps_Maya, sleep: d.Sleep_Maya, calories: d.Calories_Maya },
          { name: "Corentin", steps: d.Steps_Corentin, sleep: d.Sleep_Corentin, calories: d.Calories_Corentin },
          { name: "Amira", steps: d.Steps_Amira, sleep: d.Sleep_Amira, calories: d.Calories_Amira }
        ].filter(d => d.steps > 0 && d.sleep > 0))).flat();
      });

      const x = d3.scaleLinear()
        .domain([0, Math.ceil(d3.max(processedData.flat(), d => d.steps))])
        .range([0, width]);

      const y = d3.scaleLinear()
        .domain([0, 18])
        .range([height, 0]);

      const radius = d3.scaleSqrt()
        .domain([0, Math.ceil(d3.max(processedData.flat(), d => d.calories))])
        .range([3, 15]);

      g.append("g")
        .attr("transform", `translate(0,${height})`)
        .call(d3.axisBottom(x).ticks(10))
        .append("text")
        .attr("fill", "black")
        .attr("x", width / 2)
        .attr("y", 40)
        .attr("text-anchor", "middle")
        .text("Steps");

      g.append("g")
        .call(d3.axisLeft(y))
        .append("text")
        .attr("fill", "black")
        .attr("transform", "rotate(-90)")
        .attr("x", -height / 2)
        .attr("y", -40)
        .attr("text-anchor", "middle")
        .text("Sleep (hours)");

      const legend = svg.append("g")
        .attr("transform", `translate(${width + 20}, 50)`);

      legend.selectAll("rect")
        .data(Object.keys(colorMap))
        .enter()
        .append("rect")
        .attr("x", 0)
        .attr("y", (d, i) => i * 20)
        .attr("width", 15)
        .attr("height", 15)
        .attr("fill", d => colorMap[d]);

      legend.selectAll("text")
        .data(Object.keys(colorMap))
        .enter()
        .append("text")
        .attr("x", 20)
        .attr("y", (d, i) => i * 20 + 12)
        .text(d => d);

      const slider = document.getElementById("date-slider");
      const playButton = document.getElementById("play-button");
      let playing = false;
      let interval;

      slider.max = processedData.length - 1;

      const update = (index) => {
        const currentData = processedData[index];
        const weekLabel = Array.from(groupedData.keys())[index];

        document.getElementById("date-label").textContent = weekLabel;

        g.selectAll("circle").remove();

        g.selectAll("circle")
          .data(currentData)
          .enter()
          .append("circle")
          .attr("cx", d => x(d.steps))
          .attr("cy", d => y(d.sleep))
          .attr("r", d => radius(d.calories))
          .attr("fill", d => colorMap[d.name])
          .attr("opacity", 0.7)
          .on("mouseover", (event, d) => {
            tooltip.style("visibility", "visible")
              .text(`${d.name}: Steps: ${d.steps}, Sleep: ${d.sleep}, Calories: ${d.calories}`);
          })
          .on("mousemove", event => {
            tooltip.style("top", `${event.pageY - 10}px`)
              .style("left", `${event.pageX + 10}px`);
          })
          .on("mouseout", () => {
            tooltip.style("visibility", "hidden");
          });
      };

      playButton.addEventListener("click", () => {
        if (!playing) {
          playing = true;
          playButton.textContent = "Pause";
          let index = 0;
          interval = setInterval(() => {
            if (index >= processedData.length) {
              clearInterval(interval);
              playButton.textContent = "Play";
              playing = false;
            } else {
              slider.value = index;
              update(index);
              index++;
            }
          }, 800);
        } else {
          clearInterval(interval);
          playButton.textContent = "Play";
          playing = false;
        }
      });

      slider.addEventListener("input", (event) => update(+event.target.value));

      update(0);
    })
    .catch(error => console.error("Error loading data:", error));
}
// Visu 6
function renderRadialDistanceChart() {
  fetch("../static/js/final_combined_with_all_data.json")
    .then((response) => response.json())
    .then((data) => {
      const width = 300;
      const height = 300;
      const innerRadius = 30;
      const outerRadius = Math.min(width, height) / 2 - 20;

      // Filter data
      const filteredData = data.filter((d) => {
        const date = new Date(d.date);
        return date >= new Date("2023-10-01") && date <= new Date("2024-12-31");
      });

      // Group data by ISO week
      const groupedData = d3.group(filteredData, (d) => {
        const date = new Date(d.date);
        const weekNumber = getISOWeekNumber(date);
        return `${date.getFullYear()}-W${weekNumber}`;
      });

      const processedData = Array.from(groupedData, ([week, records]) => {
        const aggregated = {
          week: week,
          year: week.split("-")[0],
          Distance_Anis: d3.sum(records, (d) => (d.Distance_Anis > 0 ? d.Distance_Anis : 0)),
          Distance_Maya: d3.sum(records, (d) => (d.Distance_Maya > 0 ? d.Distance_Maya : 0)),
          Distance_Corentin: d3.sum(records, (d) => (d.Distance_Corentin > 0 ? d.Distance_Corentin : 0)),
          Distance_Amira: d3.sum(records, (d) => (d.Distance_Amira > 0 ? d.Distance_Amira : 0)),
          Sleep_Anis: d3.mean(records, (d) => (d.Sleep_Anis > 0 ? d.Sleep_Anis : 0)),
          Sleep_Maya: d3.mean(records, (d) => (d.Sleep_Maya > 0 ? d.Sleep_Maya : 0)),
          Sleep_Corentin: d3.mean(records, (d) => (d.Sleep_Corentin > 0 ? d.Sleep_Corentin : 0)),
          Sleep_Amira: d3.mean(records, (d) => (d.Sleep_Amira > 0 ? d.Sleep_Amira : 0)),
        };
        return aggregated;
      });

      const users = ["Anis", "Maya", "Corentin", "Amira"];
      users.forEach((user) => {
        const personKey = `Distance_${user}`;
        const sleepKey = `Sleep_${user}`;

        d3.select(`#chart-${user}`).html(""); // Clear the previous chart

        const svg = d3.select(`#chart-${user}`)
          .append("svg")
          .attr("width", width)
          .attr("height", height)
          .attr("viewBox", [-width / 2, -height / 2, width, height])
          .attr("style", "width: 100%; height: auto; font: 10px sans-serif;");

        // Tooltip
        const tooltip = d3.select("body").append("div")
          .attr("class", "tooltip-radial")
          .style("opacity", 0)
          .style("position", "absolute")
          .style("background", "rgba(0, 0, 0, 0.7)")
          .style("color", "white")
          .style("padding", "8px")
          .style("border-radius", "4px")
          .style("pointer-events", "none");

        // Scales
        const x = d3.scaleBand()
          .domain(processedData.map((d) => d.week))
          .range([0, 2 * Math.PI])
          .align(0);

        const y = d3.scaleRadial()
          .domain([0, d3.max(processedData, (d) => d[personKey])])
          .range([innerRadius, outerRadius]);

        const color = d3.scaleLinear()
          .domain([0, d3.max(processedData, (d) => d[sleepKey])])
          .range(["lightblue", "darkblue"]);

        // Bars
        svg.append("g")
          .selectAll("path")
          .data(processedData)
          .join("path")
          .attr("d", d3.arc()
            .innerRadius(innerRadius)
            .outerRadius((d) => d[personKey] > 0 ? y(d[personKey]) : y(10))
            .startAngle((d) => x(d.week))
            .endAngle((d) => x(d.week) + x.bandwidth())
            .padAngle(0.02)
            .padRadius(innerRadius))
          .attr("fill", (d) => d[personKey] > 0 ? color(d[sleepKey]) : "#ccc")
          .on("mouseover", function (event, d) {
            tooltip.transition().duration(200).style("opacity", 0.9);
            tooltip.html(`
              <strong>${user}</strong><br>
              Semaine : ${d.week}<br>
              Distance : ${d[personKey] > 0 ? d[personKey].toFixed(2) : "N/A"} km<br>
              Sommeil : ${d[sleepKey] > 0 ? d[sleepKey].toFixed(2) + "h" : "N/A"}
            `)
              .style("left", `${event.pageX + 10}px`)
              .style("top", `${event.pageY - 28}px`);
          })
          .on("mousemove", function (event) {
            tooltip.style("left", `${event.pageX + 10}px`).style("top", `${event.pageY - 28}px`);
          })
          .on("mouseout", function () {
            tooltip.transition().duration(500).style("opacity", 0);
          });
// Week Labels with grouped years
svg.append("g")
  .selectAll("g")
  .data(processedData)
  .join("g")
  .attr("transform", (d) => {
    const midAngle = (x(d.week) + x.bandwidth() / 2) * 180 / Math.PI - 90; // Angle médian
    const radius = outerRadius + 10; // Position juste en dehors des barres
    return `
      rotate(${midAngle})
      translate(${radius},0)
    `;
  })
  .call((g) => {
    g.append("text")
      .text((d, i) => {
        // Affiche l'année une seule fois pour la première semaine de chaque année
        if (i === 0 || d.year !== processedData[i - 1].year) {
          return `${d.year} ${d.week.split("-")[1]}`; // Année et numéro de semaine
        }
        return `${d.week.split("-")[1]}`; // Numéro de semaine
      })
      .attr("text-anchor", "middle")
      .style("font-size", "6px") // Réduction de la taille pour ne pas encombrer
      .style("fill", "#666"); // Couleur discrète pour les étiquettes
  });

        // Add user label
        svg.append("text")
          .attr("text-anchor", "middle")
          .attr("dy", "0.5em")
          .style("font-size", "10px")
          .style("font-weight", "bold")
          .text(user);

        // Radial circles
        const distanceTicks = y.ticks(5);
        const circleGroup = svg.append("g");

        circleGroup.selectAll("circle")
          .data(distanceTicks)
          .join("circle")
          .attr("r", (d) => y(d))
          .attr("fill", "none")
          .attr("stroke", "#ccc")
          .attr("stroke-dasharray", "4 2");

        circleGroup.selectAll("text")
          .data(distanceTicks)
          .join("text")
          .attr("x", 0)
          .attr("y", (d) => -y(d))
          .attr("dy", "-0.3em")
          .attr("text-anchor", "middle")
          .style("font-size", "6px")
          .text((d) => `${d.toFixed(0)} km`);
          const defs = svg.append("defs");
          const gradient = defs.append("linearGradient")
            .attr("id", "gradient")
            .attr("x1", "0%")
            .attr("y1", "0%")
            .attr("x2", "100%")
            .attr("y2", "0%");
          
          gradient.append("stop").attr("offset", "0%").attr("stop-color", "lightblue");
          gradient.append("stop").attr("offset", "100%").attr("stop-color", "darkblue");
          
          const legendTooltip = d3.select("body").append("div")
  .attr("class", "tooltip-legend")
  .style("position", "absolute")
  .style("padding", "10px")
  .style("background", "#fff")
  .style("border", "1px solid #ccc")
  .style("border-radius", "5px")
  .style("box-shadow", "0 4px 8px rgba(0, 0, 0, 0.1)") // Ajout d'un effet d'ombre
  .style("font-size", "12px") // Police ajustée
  .style("display", "none");

// Extraction des valeurs dynamiques pour Min et Max
const sleepMin = d3.min(processedData, (d) => d[sleepKey]);
const sleepMax = d3.max(processedData, (d) => d[sleepKey]);

// Afficher la légende au survol
svg.on("mouseover", (event) => {
  legendTooltip.style("display", "block")
    .style("left", `${event.pageX + 10}px`)
    .style("top", `${event.pageY}px`)
    .html(`
      <strong>Durée de sommeil</strong><br>
      <div style="width: 100px; height: 10px; background: linear-gradient(lightblue, darkblue); margin-top: 5px;"></div>
      <div style="display: flex; justify-content: space-between; margin-top: 5px;">
        <small>${sleepMin.toFixed(1)}h</small>
        <small>${sleepMax.toFixed(1)}h</small>
      </div>
      <div style="width: 100px; height: 10px; background: #ccc; margin-top: 10px;"></div>
      <small style="display: block; text-align: center; margin-top: 5px;">Valeurs manquantes</small>
    `);
});

// Masquer la légende
svg.on("mouseout", () => {
  legendTooltip.style("display", "none");
});

        
      });
    })
    .catch((error) => console.error("Error loading data:", error));

  function getISOWeekNumber(date) {
    const tempDate = new Date(date);
    tempDate.setDate(tempDate.getDate() + 4 - (tempDate.getDay() || 7));
    const yearStart = new Date(tempDate.getFullYear(), 0, 1);
    return Math.ceil(((tempDate - yearStart) / 86400000 + 1) / 7);
  }
}

document.addEventListener("DOMContentLoaded", function () {
  renderStepsVisualization();
  renderDistanceVisualization();
  renderCaloriesVisualization();
  renderSleepVisualization();
  renderSleepActivityVisualization();
  renderRadialDistanceChart()
});