
<!doctype html>
<html>
  <head>
    <title>Cardiovascular Disease Feature Network</title>
    <style>
      .links line {
        stroke: #999;
        stroke-opacity: 0.6;
      }
      .nodes circle {
        stroke: #fff;
        stroke-width: 1.5px;
      }
      .text {
        font: 12px sans-serif;
        pointer-events: none;
        text-anchor: middle;
      }
      .legend {
        margin: 20px auto;
        display: flex;
        justify-content: center;
        flex-wrap: wrap;
        gap: 15px;
      }
      .legend-item {
        display: flex;
        align-items: center;
        margin-right: 15px;
      }
      .legend-color {
        width: 12px;
        height: 12px;
        margin-right: 5px;
        display: inline-block;
        border-radius: 50%;
      }
    </style>
  </head>
  <body>
    <h2 style="text-align: center;">Cardiovascular Disease Feature Relationships</h2>
    <div class="legend">
      <div class="legend-item"><span class="legend-color" style="background:#1f77b4;"></span>Demographics</div>
      <div class="legend-item"><span class="legend-color" style="background:#2ca02c;"></span>Lifestyle</div>
      <div class="legend-item"><span class="legend-color" style="background:#d62728;"></span>Health Indicators</div>
      <div class="legend-item"><span class="legend-color" style="background:#9467bd;"></span>Outcome</div>
    </div>
    <svg width="800" height="600"></svg>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <script>
      var svg = d3.select('svg'),
        width = +svg.attr('width'),
        height = +svg.attr('height');

      // Define our 6 features with categories
      var nodes = [
        { id: 'gender', group: 1, category: 'Demographics' },          // Blue
        { id: 'smoke', group: 2, category: 'Lifestyle' },             // Green
        { id: 'alco', group: 2, category: 'Lifestyle' },              // Green
        { id: 'cholesterol', group: 3, category: 'Health Indicators' }, // Red
        { id: 'gluc', group: 3, category: 'Health Indicators' },      // Red
        { id: 'cardio', group: 4, category: 'Outcome' }               // Purple
      ];

      // Define connections between features
      var links = [
        { source: 'gender', target: 'cardio', value: 2 },
        { source: 'smoke', target: 'cardio', value: 3 },
        { source: 'alco', target: 'cardio', value: 2 },
        { source: 'cholesterol', target: 'cardio', value: 4 },
        { source: 'gluc', target: 'cardio', value: 3 },
        { source: 'smoke', target: 'alco', value: 2 },
        { source: 'cholesterol', target: 'gluc', value: 2 },
        { source: 'gender', target: 'smoke', value: 1 },
        { source: 'gender', target: 'cholesterol', value: 1 }
      ];

      var color = d3.scaleOrdinal()
        .domain(["Demographics", "Lifestyle", "Health Indicators", "Outcome"])
        .range(["#1f77b4", "#2ca02c", "#d62728", "#9467bd"]);

      var simulation = d3
        .forceSimulation(nodes)
        .force(
          'link',
          d3
            .forceLink(links)
            .id((d) => d.id)
            .distance(100),
        )
        .force('charge', d3.forceManyBody().strength(-400))
        .force(
          'center',
          d3.forceCenter(width / 2, height / 2),
        )
        .force('collision', d3.forceCollide().radius(20));

      var link = svg
        .append('g')
        .attr('class', 'links')
        .selectAll('line')
        .data(links)
        .enter()
        .append('line')
        .attr('stroke-width', (d) => d.value);

      var node = svg
        .append('g')
        .attr('class', 'nodes')
        .selectAll('circle')
        .data(nodes)
        .enter()
        .append('circle')
        .attr('r', (d) => d.id === 'cardio' ? 15 : 12) // Make cardio node larger
        .attr('fill', (d) => color(d.category))
        .call(
          d3
            .drag()
            .on('start', dragstarted)
            .on('drag', dragged)
            .on('end', dragended),
        );

      // Add tooltips
      node.append('title')
        .text(d => {
          if (d.id === 'gender') return "Gender (1=Female, 2=Male)";
          if (d.id === 'smoke') return "Smoking (0=No, 1=Yes)";
          if (d.id === 'alco') return "Alcohol (0=No, 1=Yes)";
          if (d.id === 'cholesterol') return "Cholesterol (1=Normal, 2=Above Normal, 3=High)";
          if (d.id === 'gluc') return "Glucose (1=Normal, 2=Above Normal, 3=High)";
          if (d.id === 'cardio') return "Cardiovascular Disease (0=No, 1=Yes)";
          return d.id;
        });

      var label = svg
        .append('g')
        .attr('class', 'labels')
        .selectAll('text')
        .data(nodes)
        .enter()
        .append('text')
        .attr('class', 'text')
        .text((d) => d.id)
        .attr('x', 8)
        .attr('y', 3);

      simulation.nodes(nodes).on('tick', ticked);

      simulation.force('link').links(links);

      function ticked() {
        link
          .attr('x1', (d) => d.source.x)
          .attr('y1', (d) => d.source.y)
          .attr('x2', (d) => d.target.x)
          .attr('y2', (d) => d.target.y);

        node.attr('cx', (d) => d.x).attr('cy', (d) => d.y);

        label.attr('x', (d) => d.x).attr('y', (d) => d.y);
      }

      function dragstarted(d) {
        if (!d3.event.active)
          simulation.alphaTarget(0.3).restart();
        d.fx = d.x;
        d.fy = d.y;
      }

      function dragged(d) {
        d.fx = d3.event.x;
        d.fy = d3.event.y;
      }

      function dragended(d) {
        if (!d3.event.active) simulation.alphaTarget(0);
        d.fx = null;
        d.fy = null;
      }
    </script>
  </body>
</html>