Skip to content
Snippets Groups Projects
script.js 3.92 KiB
Newer Older
  • Learn to ignore specific revisions
  • fetch("../final_combined_with_all_data.json")
    
    .then(response => response.json())
    .then(data => {
      const width = 600;
      const height = 600;
      const innerRadius = 50;
      const outerRadius = Math.min(width, height) / 2 - 100;
    
      // 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,
          Distance_Anis: d3.sum(records, d => d.Distance_Anis || 0),
          Distance_Maya: d3.sum(records, d => d.Distance_Maya || 0),
          Distance_Corentin: d3.sum(records, d => d.Distance_Corentin || 0),
          Distance_Amira: d3.sum(records, d => d.Distance_Amira || 0),
          Sleep_Anis: d3.mean(records, d => d.Sleep_Anis || 0),
          Sleep_Maya: d3.mean(records, d => d.Sleep_Maya || 0),
          Sleep_Corentin: d3.mean(records, d => d.Sleep_Corentin || 0),
          Sleep_Amira: d3.mean(records, d => d.Sleep_Amira || 0),
        };
        return aggregated;
      });
    
      // Dropdown change event
      const dropdown = document.getElementById("personDropdown");
      dropdown.addEventListener("change", () => updateChart(dropdown.value));
    
      // Initial chart rendering
      updateChart(dropdown.value);
    
      function updateChart(personKey) {
        const sleepKey = personKey.replace("Distance", "Sleep");
        d3.select("#chart").html(""); // Clear the previous chart
    
        const svg = d3.select("#chart")
          .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;");
    
        // 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 => y(d[personKey]))
            .startAngle(d => x(d.week))
            .endAngle(d => x(d.week) + x.bandwidth())
            .padAngle(0.02)
            .padRadius(innerRadius))
          .attr("fill", d => color(d[sleepKey]))
          .append("title")
          .text(d => `${d.week}\nDistance: ${d[personKey].toFixed(2)}\nSleep: ${d[sleepKey].toFixed(2)}h`);
    
        // Labels
    
        svg.append("g")
    
          .selectAll("g")
    
          .data(x.domain())
          .join("g")
    
          .attr("transform", d => `
            rotate(${((x(d) + x.bandwidth() / 2) * 180 / Math.PI - 90)})
            translate(${outerRadius + 25},0)
          `)
          .call(g => g.append("text")
            .text(d => d)
            .attr("text-anchor", "middle"));
    
        // Legend
    
        svg.append("g")
    
          .selectAll("g")
    
          .data(["Low Sleep", "High Sleep"])
    
          .join("g")
    
          .attr("transform", (d, i) => `translate(-30,${(2 - i - 2) * 10})`)
          .call(g => g.append("rect")
            .attr("width", 10)
            .attr("height", 10)
            .attr("fill", (d, i) => i === 0 ? "lightblue" : "darkblue"))
          .call(g => g.append("text")
            .text(d => d)
            .attr("x", 20)
            .attr("y", 9));
      }
    
      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);
      }
    })
    .catch(error => console.error("Error loading data:", error));