versio 0.1
d3 = require("d3@7")
data = d3.csv("https://gist.githubusercontent.com/Juuso1/4b92d153a02263380b2560f2e7e42d09/raw/muuttoliike_kangasala_2021.csv", d3.autoType)
data_2 = d3.csv("https://gist.githubusercontent.com/Juuso1/f2fcdaf8c6053f315f1bc1a67bbd4c61/raw/kangasala_tampere_pienalue_2021.csv", d3.autoType)
data_3 = d3.csv("https://gist.githubusercontent.com/Juuso1/722dc5a035c757f2032125fbea751142/raw/kangasala_lempaala_pienalue_2021.csv", d3.autoType)
data_4 = d3.csv("https://gist.githubusercontent.com/Juuso1/145ce37f1f10433c6cbc4831f244602e/raw/kangasala_nokia_pienalue_2021.csv", d3.autoType)
data_5 = d3.csv("https://gist.githubusercontent.com/Juuso1/7951de54348c5de46db9e4bf3173afe6/raw/kangasala_orivesi_pienalue.csv", d3.autoType)
data_6 = d3.csv("https://gist.githubusercontent.com/Juuso1/e66c94b930972e105c450045aea8c7b2/raw/kangasala_pirkkala_pienalue_2021.csv", d3.autoType)
data_7 = d3.csv("https://gist.githubusercontent.com/Juuso1/5690853d57d677826555a37f759c1c95/raw/kangasala_palkane_pienalue_2021.csv", d3.autoType)
data_8 = d3.csv("https://gist.githubusercontent.com/Juuso1/dcb98508964bc6c255280637be4135cc/raw/kangasala_akaa_pienalue.csv", d3.autoType)
data_9 = d3.csv("https://gist.githubusercontent.com/Juuso1/22b5fe1ec9e3a8bf353c7b17a301d4a9/raw/kangasala_valkeakoski-pienalueet.csv", d3.autoType)
data_10 = d3.csv("https://gist.githubusercontent.com/Juuso1/47bebabe370259a9a5ae2709460fac9b/raw/kangasala_ylojarvi_pienalueet.csv", d3.autoType)chord = d3.chordDirected()
    .padAngle(0.8 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix = {
  const index = new Map(names.map((name, i) => [name, i]));
  const matrix = Array.from(index, () => new Array(names.length).fill(0));
  for (const {source, target, value} of data) matrix[index.get(source)][index.get(target)] += value;
  return matrix;
}chart = {
  let sum_target;
  let sum_source;
  let sum_yht;
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord(matrix);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
           sum_target = d3.sum(chords, c => (c.target.index === d.index) * c.target.value);
           sum_source = d3.sum(chords, c => (c.source.index === d.index) * c.source.value);
           sum_yht = sum_target-sum_source;
            if (sum_yht > 0) { return "#009651" }
            else if (sum_yht == 0) { return "#28336C" }
            else    { return "#DE232F" }
        })
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names[d.index])
            .attr("fill", d => {
           sum_target = d3.sum(chords, c => (c.target.index === d.index) * c.target.value);
           sum_source = d3.sum(chords, c => (c.source.index === d.index) * c.source.value);
           sum_yht = sum_target-sum_source;
            if (sum_yht > 0) { return "#009651" }
            else if (sum_yht == 0) { return "#28336C" }
            else    { return "#DE232F" }
        });
  group.append("title")
      .text(d => `${names[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
      //.attr("fill", d => color(names[d.source.index]))
      .attr("fill", d => {
            //if (names[d.index] === "Kangasala") {return "#DE232F"}
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon)
    .append("title")
      .text(d => `${names[d.source.index]} --> ${names[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_2 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_2 = {
  const index = new Map(names_2.map((name, i) => [name, i]));
  const matrix_2 = Array.from(index, () => new Array(names_2.length).fill(0));
  for (const {source, target, value} of data_2) matrix_2[index.get(source)][index.get(target)] += value;
  return matrix_2;
}chart_2 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_2(matrix_2);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_2[d.index])
        .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_2[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
        .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_2)
    .append("title")
      .text(d => `${names_2[d.source.index]} --> ${names_2[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_3 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_3 = {
  const index = new Map(names_3.map((name, i) => [name, i]));
  const matrix_3 = Array.from(index, () => new Array(names_3.length).fill(0));
  for (const {source, target, value} of data_3) matrix_3[index.get(source)][index.get(target)] += value;
  return matrix_3;
}chart_3 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_3(matrix_3);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_3[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_3[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
        .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_3)
    .append("title")
      .text(d => `${names_3[d.source.index]} --> ${names_3[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_4 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_4 = {
  const index = new Map(names_4.map((name, i) => [name, i]));
  const matrix_4 = Array.from(index, () => new Array(names_4.length).fill(0));
  for (const {source, target, value} of data_4) matrix_4[index.get(source)][index.get(target)] += value;
  return matrix_4;
}chart_4 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_4(matrix_4);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_4[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_4[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_4)
    .append("title")
      .text(d => `${names_4[d.source.index]} --> ${names_4[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_5 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_5 = {
  const index = new Map(names_5.map((name, i) => [name, i]));
  const matrix_5 = Array.from(index, () => new Array(names_5.length).fill(0));
  for (const {source, target, value} of data_5) matrix_5[index.get(source)][index.get(target)] += value;
  return matrix_5;
}chart_5 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_5(matrix_5);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_5[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_5[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_5)
    .append("title")
      .text(d => `${names_5[d.source.index]} --> ${names_5[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_6 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_6 = {
  const index = new Map(names_6.map((name, i) => [name, i]));
  const matrix_6 = Array.from(index, () => new Array(names_6.length).fill(0));
  for (const {source, target, value} of data_6) matrix_6[index.get(source)][index.get(target)] += value;
  return matrix_6;
}chart_6 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_6(matrix_6);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_6[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_6[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_6)
    .append("title")
      .text(d => `${names_6[d.source.index]} --> ${names_6[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_7 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_7 = {
  const index = new Map(names_7.map((name, i) => [name, i]));
  const matrix_7 = Array.from(index, () => new Array(names_7.length).fill(0));
  for (const {source, target, value} of data_7) matrix_7[index.get(source)][index.get(target)] += value;
  return matrix_7;
}chart_7 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_7(matrix_7);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_7[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_7[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_7)
    .append("title")
      .text(d => `${names_7[d.source.index]} --> ${names_7[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_8 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_8 = {
  const index = new Map(names_8.map((name, i) => [name, i]));
  const matrix_8 = Array.from(index, () => new Array(names_8.length).fill(0));
  for (const {source, target, value} of data_8) matrix_8[index.get(source)][index.get(target)] += value;
  return matrix_8;
}chart_8 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_8(matrix_8);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_8[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_8[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_8)
    .append("title")
      .text(d => `${names_8[d.source.index]} --> ${names_8[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_9 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_9 = {
  const index = new Map(names_9.map((name, i) => [name, i]));
  const matrix_9 = Array.from(index, () => new Array(names_9.length).fill(0));
  for (const {source, target, value} of data_9) matrix_9[index.get(source)][index.get(target)] += value;
  return matrix_9;
}chart_9 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_9(matrix_9);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_9[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_9[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_9)
    .append("title")
      .text(d => `${names_9[d.source.index]} --> ${names_9[d.target.index]} ${d.source.value}`);
  return svg.node();
}chord_10 = d3.chordDirected()
    .padAngle(1 / innerRadius)
    .sortSubgroups(d3.ascending)
    .sortChords(d3.ascending)matrix_10 = {
  const index = new Map(names_10.map((name, i) => [name, i]));
  const matrix_10 = Array.from(index, () => new Array(names_10.length).fill(0));
  for (const {source, target, value} of data_10) matrix_10[index.get(source)][index.get(target)] += value;
  return matrix_10;
}chart_10 = {
  const svg = d3.create("svg")
      .attr("viewBox", [-width / 2, -height / 3, width, height]);
  const chords = chord_10(matrix_10);
  const group = svg.append("g")
      .attr("font-size", 2)
      .attr("font-family", "Century Gothic")
      .attr("font-weight", "bold")
    .selectAll("g")
    .data(chords.groups)
    .join("g");
  group.append("path")
      .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;})
      .attr("d", arc);
  
  group.append("text")
      .each(d => (d.angle = (d.startAngle + d.endAngle) / 2))
      .attr("dy", "0.35em")
      .attr("transform", d => `
        rotate(${(d.angle * 180 / Math.PI - 90)})
        translate(${outerRadius + 5})
        ${d.angle > Math.PI ? "rotate(180)" : ""}
      `)
      .attr("text-anchor", d => d.angle > Math.PI ? "end" : null)
      .text(d => names_10[d.index])
              .attr("fill", d => {
            if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#009651"}
            else    { return "#DE232F" }
        ;});
  group.append("title")
      .text(d => `${names_10[d.index]}
${d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} lähtee →
${d3.sum(chords, c => (c.target.index === d.index) * c.source.value)} tulee ←
${d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)} netto =`);  
  svg.append("g")
      .attr("fill-opacity", 0.75)
    .selectAll("path")
    .data(chords)
    .join("path")
      .style("mix-blend-mode", "multiply")
              .attr("fill", d => {
                        if ((d3.sum(chords, c => (c.target.index === d.index) * c.target.value)- d3.sum(chords, c => (c.source.index === d.index) * c.source.value)) >= 0) {return "#28336C"}
            else    { return "#28336C" }
        ;})
      .attr("d", ribbon_10)
    .append("title")
      .text(d => `${names_10[d.source.index]} --> ${names_10[d.target.index]} ${d.source.value}`);
  return svg.node();
}
Copyright 2023 Kangasalan kaupunki, LGPL 2.1