<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Graphe du Secret Santa</title>
    <title>D3.js Interactive Cycle Graph with Alternating Curved Arrows</title>
    <script src="https://d3js.org/d3.v5.min.js"></script>
    <style>
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        svg {
            display: block;
        }

        .node {
            cursor: pointer;
        }

        .legend text {
            font-size: 10px;
            font-family: sans-serif;
            text-anchor: start;
        }
    </style>
</head>
<body>

<script>
    // Données du graphe
    d3.csv("santa.csv").then(function(data) {

        // Dimensions du SVG en plein écran
        const width = window.innerWidth;
        const height = window.innerHeight;

        const uniqueNames = data.map(d => d.Source);

        // Création des nœuds avec des positions initiales
        const nodes = uniqueNames.map((name, index) => ({id: index, label: name}));

        const links = data.map((d, i) => ({
            source: i,
            target: uniqueNames.indexOf(d.Cible)
        }));

        links.push({ source: 0, target: 1 });

        // Création de la force de simulation avec une force de répulsion plus forte
        const simulation = d3.forceSimulation(nodes)
            .force("charge", d3.forceManyBody().strength(-300))
            .force("link", d3.forceLink(links).distance(100))
            .force("center", d3.forceCenter(width / 2, height / 2))
            .force("collide", d3.forceCollide().radius(20))
            .force("x", d3.forceX().strength(0.1).x(width / 2))
            .force("y", d3.forceY().strength(0.1).y(height / 2));

        // Création du SVG avec zoom
        const svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height)
            .call(d3.zoom().on("zoom", function () {
                svg.attr("transform", d3.event.transform)
            }))
            .append("g");

        // Ajout des flèches
        svg.append("defs").selectAll("marker")
            .data(["arrow"])
            .enter().append("marker")
            .attr("id", function (d) {
                return d;
            })
            .attr("viewBox", "0 -5 10 10")
            .attr("refX", 18)
            .attr("refY", 0)
            .attr("markerWidth", 4)
            .attr("markerHeight", 4)
            .attr("orient", "auto")
            .append("path")
            .attr("d", "M0,-5L10,0L0,5")
            .attr("class", "arrow-head");

        // Ajout des liens
        const link = svg.selectAll("path")
            .data(links)
            .enter().append("path")
            .attr("fill", "none")
            .attr("stroke", "#ee288b")
            .attr("stroke-width", "2")
            .attr("marker-end", "url(#arrow)");

        // Ajout des nœuds
        const node = svg.selectAll(".node")
            .data(nodes)
            .enter().append("g")
            .attr("class", "node")
            .call(d3.drag()
                .on("start", dragstarted)
                .on("drag", dragged)
                .on("end", dragended));

        node.append("circle")
            .attr("r", 3)  // Taille des points noirs
            .attr("fill", "#000");  // Couleur des points noirs

        // Ajout des légendes pour les nœuds
        const legend = svg.selectAll(".legend")
            .data(nodes)
            .enter().append("g")
            .attr("class", "legend")
            .attr("transform", function (d) {
                return "translate(" + (d.x + 10) + "," + (d.y) + ")";
            });

        legend.append("text")
            .text(function (d) {
                return d.label;
            });

        // Met à jour la position des éléments à chaque itération de la simulation
        simulation.on("tick", function () {
            link.attr("d", function (d) {
                const dx = d.target.x - d.source.x,
                    dy = d.target.y - d.source.y,
                    dr = Math.sqrt(dx * dx + dy * dy),
                    sweep = 1;
                return "M" + d.source.x + "," + d.source.y +
                    "A" + dr + "," + dr + " 0 0," + sweep + " " + d.target.x + "," + d.target.y;
            });

            node.attr("transform", function (d) {
                return "translate(" + d.x + "," + d.y + ")";
            });

            legend.attr("transform", function (d) {
                return "translate(" + (d.x + 10) + "," + (d.y) + ")";
            });
        });

        // Fonctions de gestion du glisser-déposer
        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>