|
|
|
@ -1,18 +1,131 @@ |
|
|
|
|
const Diagram = { |
|
|
|
|
// clear: () => d3.select('svg').remove(),
|
|
|
|
|
clear: () => d3.select('svg').selectAll("*").remove(), |
|
|
|
|
|
|
|
|
|
swap: (i, j) => { |
|
|
|
|
const fst = Object.assign({}, chords.groups[i]); |
|
|
|
|
const snd = Object.assign({}, chords.groups[j]); |
|
|
|
|
|
|
|
|
|
// Calculate and apply offsets for adjacent group arcs.
|
|
|
|
|
deltaFst = snd.endAngle - fst.endAngle; |
|
|
|
|
deltaSnd = snd.startAngle - fst.startAngle |
|
|
|
|
|
|
|
|
|
chords.groups[i].startAngle += deltaFst; |
|
|
|
|
chords.groups[i].endAngle += deltaFst; |
|
|
|
|
|
|
|
|
|
chords.groups[j].startAngle -= deltaSnd; |
|
|
|
|
chords.groups[j].endAngle -= deltaSnd; |
|
|
|
|
|
|
|
|
|
// Apply offsets to relevant chords.
|
|
|
|
|
chords.forEach((v,i) => { |
|
|
|
|
const sourceProps = {}; |
|
|
|
|
const targetProps = {} |
|
|
|
|
|
|
|
|
|
// Adjust source and target arcs for first index.
|
|
|
|
|
if (v.source.index === fst.index) { |
|
|
|
|
sourceProps.index = snd.index; |
|
|
|
|
sourceProps.startAngle = v.source.startAngle + deltaFst; |
|
|
|
|
sourceProps.endAngle = v.source.endAngle + deltaFst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.target.index === fst.index) { |
|
|
|
|
targetProps.index = snd.index; |
|
|
|
|
targetProps.startAngle = v.target.startAngle + deltaFst; |
|
|
|
|
targetProps.endAngle = v.target.endAngle + deltaFst; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.source.subindex === fst.index) { |
|
|
|
|
sourceProps.subindex = snd.index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.target.subindex === fst.index) { |
|
|
|
|
targetProps.subindex = snd.index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Adjust source and target arcs for second index.
|
|
|
|
|
if (v.source.index === snd.index) { |
|
|
|
|
sourceProps.index = fst.index; |
|
|
|
|
sourceProps.startAngle = v.source.startAngle - deltaSnd; |
|
|
|
|
sourceProps.endAngle = v.source.endAngle - deltaSnd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.target.index === snd.index) { |
|
|
|
|
targetProps.index = fst.index; |
|
|
|
|
targetProps.startAngle = v.target.startAngle - deltaSnd; |
|
|
|
|
targetProps.endAngle = v.target.endAngle - deltaSnd; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.source.subindex === snd.index) { |
|
|
|
|
sourceProps.subindex = fst.index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (v.target.subindex === snd.index) { |
|
|
|
|
targetProps.subindex = fst.index; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Object.assign(v.source, sourceProps) |
|
|
|
|
Object.assign(v.target, targetProps) |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
return chords; |
|
|
|
|
|
|
|
|
|
// // json.tourneys[eventKey].teams.sort()
|
|
|
|
|
//
|
|
|
|
|
// sortKey = "goalsFor"
|
|
|
|
|
//
|
|
|
|
|
// switch (sortKey) {
|
|
|
|
|
// case 'goalsFor':
|
|
|
|
|
// // console.info(json.tourneys[eventKey].teams)/
|
|
|
|
|
// // return json.tourneys[eventKey].teams;
|
|
|
|
|
//
|
|
|
|
|
// const teams = json.tourneys[eventKey].teams
|
|
|
|
|
// .slice()
|
|
|
|
|
// .sort((a, b) => {
|
|
|
|
|
// const n1 = json.countries[json.teams[a]].n;
|
|
|
|
|
// const n2 = json.countries[json.teams[b]].n;
|
|
|
|
|
//
|
|
|
|
|
// if (n1 < n2) {
|
|
|
|
|
// return -1;
|
|
|
|
|
// }
|
|
|
|
|
// else if (n1 > n2) {
|
|
|
|
|
// return 1;
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// return 0;
|
|
|
|
|
// });
|
|
|
|
|
//
|
|
|
|
|
// console.warn(teams.map(v => {
|
|
|
|
|
// return json.countries[json.teams[v]].n
|
|
|
|
|
// }))
|
|
|
|
|
//
|
|
|
|
|
// // console.warn(teams.map(a => json.countries[json.teams[a]].n))
|
|
|
|
|
//
|
|
|
|
|
// return teams;
|
|
|
|
|
// break;
|
|
|
|
|
//
|
|
|
|
|
// case 'goalsAgainst':
|
|
|
|
|
// break;
|
|
|
|
|
//
|
|
|
|
|
// case 'countryName':
|
|
|
|
|
// break;
|
|
|
|
|
//
|
|
|
|
|
// case 'countryPopulation':
|
|
|
|
|
// break;
|
|
|
|
|
// }
|
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
build: (data, eventIndex, metaMatrix, chordMatrix) => { |
|
|
|
|
const svg = d3.select("svg"), |
|
|
|
|
width = +svg.attr("width"), |
|
|
|
|
height = +svg.attr("height"), |
|
|
|
|
outerArcThickness = 5, |
|
|
|
|
outerRadius = Math.min(width, height) * 0.5 - 100, |
|
|
|
|
outerRadius = Math.min(width, height) * 0.5 - 125, |
|
|
|
|
innerRadius = outerRadius - outerArcThickness; |
|
|
|
|
|
|
|
|
|
const chord = d3.chord() |
|
|
|
|
.padAngle(0.05); |
|
|
|
|
|
|
|
|
|
const sortedChords = Diagram.sort(chord(chordMatrix)); |
|
|
|
|
|
|
|
|
|
const arc = d3.arc() |
|
|
|
|
.innerRadius(innerRadius) |
|
|
|
|
.outerRadius(outerRadius); |
|
|
|
@ -35,46 +148,46 @@ const Diagram = { |
|
|
|
|
|
|
|
|
|
const g = svg.append("g") |
|
|
|
|
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")") |
|
|
|
|
.datum(chord(chordMatrix)); |
|
|
|
|
.datum(sortedChords); |
|
|
|
|
|
|
|
|
|
const group = g.append("g") |
|
|
|
|
.attr("class", "groups") |
|
|
|
|
.selectAll("g") |
|
|
|
|
.data(function(chords) { return chords.groups; }) |
|
|
|
|
.data(chords => chords.groups) |
|
|
|
|
.enter().append("g"); |
|
|
|
|
|
|
|
|
|
group.append("path") |
|
|
|
|
.style("fill", function(d) { return color(d.index); }) |
|
|
|
|
.style("stroke", function(d) { return d3.rgb(color(d.index)).darker(); }) |
|
|
|
|
.style("fill", d => color(d.index)) |
|
|
|
|
.style("stroke", d => d3.rgb(color(d.index)).darker()) |
|
|
|
|
.attr("d", arc); |
|
|
|
|
|
|
|
|
|
g.append("g") |
|
|
|
|
.attr("class", "ribbons") |
|
|
|
|
.selectAll("path") |
|
|
|
|
.data(function(chords) { return chords; }) |
|
|
|
|
.enter().append("path") |
|
|
|
|
.attr("d", ribbon) |
|
|
|
|
.style("fill", function(d) { return color(d.target.index); }) |
|
|
|
|
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }) |
|
|
|
|
.attr("class", "ribbon") |
|
|
|
|
// .append("title")
|
|
|
|
|
// .text(function(d) {
|
|
|
|
|
// const meta1 = metaMatrix[d.target.index][d.source.index];
|
|
|
|
|
// const meta2 = metaMatrix[d.source.index][d.target.index];
|
|
|
|
|
//
|
|
|
|
|
// const g = meta1.game;
|
|
|
|
|
//
|
|
|
|
|
// const t1 = lookup.teams[g.t1];
|
|
|
|
|
// const t2 = lookup.teams[g.t2];
|
|
|
|
|
//
|
|
|
|
|
// const e1 = g.s1e ? `(+${g.s1e} in extended time)` : '';
|
|
|
|
|
// const e2 = g.s2e ? `(+${g.s2e} in extended time)` : '';
|
|
|
|
|
//
|
|
|
|
|
// const p1 = g.s1p ? `(+${g.s1p} in penalties)` : '';
|
|
|
|
|
// const p2 = g.s2p ? `(+${g.s2p} in penalties)` : '';
|
|
|
|
|
//
|
|
|
|
|
// return `${t1}: ${g.s1} ${e1} ${p1}\n${t2}: ${g.s2} ${e2} ${p2}`;
|
|
|
|
|
// });
|
|
|
|
|
g.append("g") |
|
|
|
|
.attr("class", "ribbons") |
|
|
|
|
.selectAll("path") |
|
|
|
|
.data(function(chords) { return chords; }) |
|
|
|
|
.enter().append("path") |
|
|
|
|
.attr("d", ribbon) |
|
|
|
|
.style("fill", function(d) { return color(d.target.index); }) |
|
|
|
|
.style("stroke", function(d) { return d3.rgb(color(d.target.index)).darker(); }) |
|
|
|
|
.attr("class", "ribbon") |
|
|
|
|
// .append("title")
|
|
|
|
|
// .text(function(d) {
|
|
|
|
|
// const meta1 = metaMatrix[d.target.index][d.source.index];
|
|
|
|
|
// const meta2 = metaMatrix[d.source.index][d.target.index];
|
|
|
|
|
//
|
|
|
|
|
// const g = meta1.game;
|
|
|
|
|
//
|
|
|
|
|
// const t1 = lookup.teams[g.t1];
|
|
|
|
|
// const t2 = lookup.teams[g.t2];
|
|
|
|
|
//
|
|
|
|
|
// const e1 = g.s1e ? `(+${g.s1e} in extended time)` : '';
|
|
|
|
|
// const e2 = g.s2e ? `(+${g.s2e} in extended time)` : '';
|
|
|
|
|
//
|
|
|
|
|
// const p1 = g.s1p ? `(+${g.s1p} in penalties)` : '';
|
|
|
|
|
// const p2 = g.s2p ? `(+${g.s2p} in penalties)` : '';
|
|
|
|
|
//
|
|
|
|
|
// return `${t1}: ${g.s1} ${e1} ${p1}\n${t2}: ${g.s2} ${e2} ${p2}`;
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
group.append("text") |
|
|
|
|
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; }) |
|
|
|
@ -92,15 +205,9 @@ const Diagram = { |
|
|
|
|
// COLOR BY CONTINENT
|
|
|
|
|
// STRANGE EXTENDED TIME CHILE-BRAZIL - FIX BY HAND? IS BECAUE se1 IS SCORE __GOING INTO__ EXTENDED TIME
|
|
|
|
|
// console.info(metaMatrix[d.index])
|
|
|
|
|
|
|
|
|
|
const t = data.tourneys[eventIndex].teams[d.index]; |
|
|
|
|
const c = data.countries[data.teams[t]]; |
|
|
|
|
return data.countries[data.teams[t]].n; |
|
|
|
|
return data.countries[data.teams[t]].n + ' ' + d.index; |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// const main = (data) => {
|
|
|
|
|
// const lookup = buildLookup(endpoints, data);
|
|
|
|
|
// const chordMatrix = buildChordMatrix(lookup.games, lookup.reducedTeams)
|
|
|
|
|
// const metaMatrix = buildMetaMatrix(lookup.games, lookup.reducedTeams)
|
|
|
|
|
// };
|
|
|
|
|