Extracting JS modules.

master
Ben Burlingham 9 years ago
parent 0819057c79
commit aefdade7ea
  1. 200
      index.html
  2. 104
      js/diagram.js
  3. 19
      js/main.js
  4. 39
      js/matrices.js
  5. 2
      js/ui.js

@ -29,6 +29,9 @@ body {
</style>
<script src="http://d3js.org/d3.v4.0.0-alpha.50.min.js"></script>
<script src="http://d3js.org/d3-chord.v0.0.min.js"></script>
<script src='js/matrices.js'></script>
<script src='js/diagram.js'></script>
<script src='js/main.js'></script>
<link rel="stylesheet" href="res/flags.min.css">
<link rel="stylesheet" href="res/options.css">
<link rel="stylesheet" href="res/events.css">
@ -201,6 +204,9 @@ body {
<div class="option-item">
<div class="option-text">Sort By Goals Scored</div>
</div>
<div class="option-item">
<div class="option-text">Sort By Country Population</div>
</div>
</div>
<div class="diagram">
@ -208,200 +214,6 @@ body {
</div>
</div>
<script>
// const buildLookup = (endpoints, result) => {
// const lookup = {};
//
// result.map((v, i) => {
// const json = JSON.parse(v);
// const address = endpoints[i].split('.').shift();
// lookup[address] = json;
// });
//
// // Team list is ~220 items; assign indices to only teams in this tournament.
// lookup.reducedTeams = lookup.games.reduce((acc, v) => {
// if (acc[v.t1] === undefined) {
// acc[v.t1] = Object.keys(acc).length;
// }
//
// return acc;
// }, {});
//
// return lookup;
// };
//
// const buildChordMatrix = (games, reducedTeams) => {
// // Create A x A array of nulls; null-null relationships are omitted.
// const empty = Array.apply(null, Array(Object.keys(reducedTeams).length));
// const result = empty.map(() => empty.map(() => null));
//
// games.forEach(v => {
// // Use indexes from reduced lists to populate final matrix.
// const t1 = reducedTeams[v.t1];
// const t2 = reducedTeams[v.t2];
//
// result[t1][t2] = v.s1 + v.s1e + v.s1p;
// result[t2][t1] = v.s2 + v.s2e + v.s2p;
// }, []);
//
// return result;
// };
//
// const teamNameFromIndex = (lookup, index) => {
// for (let i in lookup.reducedTeams) {
// if (lookup.reducedTeams[i] === index) {
// return lookup.teams[i];
// }
// }
//
// return "Unknown";
// };
//
// const main = (data) => {
// const lookup = buildLookup(endpoints, data);
// const chordMatrix = buildChordMatrix(lookup.games, lookup.reducedTeams)
// const metaMatrix = buildMetaMatrix(lookup.games, lookup.reducedTeams)
//
// const svg = d3.select("svg"),
// width = +svg.attr("width"),
// height = +svg.attr("height"),
// outerArcThickness = 5,
// outerRadius = Math.min(width, height) * 0.5 - 100,
// innerRadius = outerRadius - outerArcThickness;
//
// const chord = d3.chord()
// .padAngle(0.05);
//
// const arc = d3.arc()
// .innerRadius(innerRadius)
// .outerRadius(outerRadius);
//
// const ribbon = d3.ribbon()
// .radius(innerRadius);
//
// // const color = d3.scaleOrdinal(d3.schemeCategory20);
// // const color = d3.scaleOrdinal(d3.schemeCategory10);
// // const color = d3.scaleOrdinal(d3.interpolateCool);
// // const color = d3.scaleSequential(d3.interpolateRainbow);
//
// const color = d3.scaleLinear().domain([0,10]).range(["red", "blue"]).interpolate(d3.interpolateRgb)
//
// // const colors = ["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"];
// // const colors = ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"];
// // const colors = ["#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"];
// // const colors = ["#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#66A61E", "#E6AB02", "#A6761D", "#666666"];
// // const color = i => colors[i % colors.length];
//
// const g = svg.append("g")
// .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
// .datum(chord(chordMatrix));
//
// const group = g.append("g")
// .attr("class", "groups")
// .selectAll("g")
// .data(function(chords) { return 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(); })
// .attr("d", arc)
//
// group.append("text")
// .each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
// .attr("dy", ".35em")
// .attr("transform", function(d) {
// return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
// + "translate(" + (innerRadius + 26) + ")"
// + (d.angle > Math.PI ? "rotate(180)" : "");
// })
// .style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
// .text(function(d) {
// // SORT BY GOALS SCORED
// // SORT BY ALPHABETICAL
// // SORT BY COUNTRY SIZE
// // SORT BY COUNTRY POPULATION
// // COLOR BY CONTINENT
// // STRANGE EXTENDED TIME CHILE-BRAZIL - FIX BY HAND?
// return teamNameFromIndex(lookup, d.index);
// });
//
// 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}`;
// });
// };
const Data = {
// Identical structure of chord matrix but with { game, team }.
buildMetaMatrix: (eventKey) => {
console.info(Data.tourneys)
// const event = Data.json[eventKey];
// console.warn(event)
// const empty = Array.apply(null, Array(Object.keys(reducedTeams).length));
// const matrix = empty.map(() => empty.map(() => null));
//
// games.forEach(g => {
// const t1 = reducedTeams[g.t1];
// const t2 = reducedTeams[g.t2];
//
// matrix[t1][t2] = { game: g, team: g.t1 };
// matrix[t2][t1] = { game: g, team: g.t2 };
// }, []);
//
// return matrix;
},
};
const main = function(data) {
Object.assign(Data, JSON.parse(data));
Data.buildMetaMatrix("1930");
// Data.buildChordMatrix();
// Diagram.build();
}
//===== Entry point
const fetch = (url) => new Promise((resolve, reject) => {
const listener = ({ srcElement: req }) => {
req.status === 200 ? resolve(req.responseText) : reject("busted");
};
const req = new XMLHttpRequest();
req.addEventListener('load', listener);
req.open('GET', url);
req.send();
});
fetch('worldcup.json').then(main);
</script>
<div class="notes">
<h5>Lessons learned</h5>
scaleOrdinal vs scaleLinear (only 2 colors!) vs interpolateCool vs d3.schemeColor20c<br>

@ -0,0 +1,104 @@
const Diagram = {
build: (eventIndex, data, 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,
innerRadius = outerRadius - outerArcThickness;
const chord = d3.chord()
.padAngle(0.05);
const arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
const ribbon = d3.ribbon()
.radius(innerRadius);
// const color = d3.scaleOrdinal(d3.schemeCategory20);
// const color = d3.scaleOrdinal(d3.schemeCategory10);
// const color = d3.scaleOrdinal(d3.interpolateCool);
// const color = d3.scaleSequential(d3.interpolateRainbow);
const color = d3.scaleLinear().domain([0,10]).range(["red", "blue"]).interpolate(d3.interpolateRgb)
// const colors = ["#f1eef6","#d4b9da","#c994c7","#df65b0","#e7298a","#ce1256","#91003f"];
// const colors = ["#ffffcc","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#0c2c84"];
// const colors = ["#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"];
// const colors = ["#1B9E77", "#D95F02", "#7570B3", "#E7298A", "#66A61E", "#E6AB02", "#A6761D", "#666666"];
// const color = i => colors[i % colors.length];
const g = svg.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
.datum(chord(chordMatrix));
const group = g.append("g")
.attr("class", "groups")
.selectAll("g")
.data(function(chords) { return 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(); })
.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}`;
// });
group.append("text")
.each(function(d) { d.angle = (d.startAngle + d.endAngle) / 2; })
.attr("dy", ".35em")
.attr("transform", function(d) {
return "rotate(" + (d.angle * 180 / Math.PI - 90) + ")"
+ "translate(" + (innerRadius + 26) + ")"
+ (d.angle > Math.PI ? "rotate(180)" : "");
})
.style("text-anchor", function(d) { return d.angle > Math.PI ? "end" : null; })
.text(function(d) {
// SORT BY GOALS SCORED
// SORT BY ALPHABETICAL
// SORT BY COUNTRY SIZE
// SORT BY COUNTRY POPULATION
// 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;
});
},
};
// const main = (data) => {
// const lookup = buildLookup(endpoints, data);
// const chordMatrix = buildChordMatrix(lookup.games, lookup.reducedTeams)
// const metaMatrix = buildMetaMatrix(lookup.games, lookup.reducedTeams)
// };

@ -0,0 +1,19 @@
const fetch = (url) => new Promise((resolve, reject) => {
const listener = ({ srcElement: req }) => {
req.status === 200 ? resolve(req.responseText) : reject("busted");
};
const req = new XMLHttpRequest();
req.addEventListener('load', listener);
req.open('GET', url);
req.send();
});
const main = function(strData) {
const json = JSON.parse(strData);
const metaMatrix = Matrices.buildMetaMatrix(json, "1930");
const chordMatrix = Matrices.buildChordMatrix(json, "1930");
Diagram.build("1930", json, metaMatrix, chordMatrix);
}
fetch('worldcup.json').then(main);

@ -0,0 +1,39 @@
const Matrices = {
// A x A array of nulls; null-null relationships are omitted in chord diagram.
createEmptyMatrix: (len) => {
const empty = Array.apply(null, Array(len));
return empty.map(() => empty.map(() => null));
},
// Identical structure of chord matrix but with { game, team }.
buildMetaMatrix: (json, eventKey) => {
const teams = json.tourneys[eventKey].teams;
const matrix = Matrices.createEmptyMatrix(teams.length);
json.tourneys[eventKey].games.forEach(g => {
const i1 = teams.indexOf(g.t1);
const i2 = teams.indexOf(g.t2);
matrix[i1][i2] = { game: g, team: g.t1 };
matrix[i2][i1] = { game: g, team: g.t2 };
}, []);
return matrix;
},
// Scalar data points (sum of goals scored).
buildChordMatrix: (json, eventKey) => {
const teams = json.tourneys[eventKey].teams;
const matrix = Matrices.createEmptyMatrix(teams.length);
json.tourneys[eventKey].games.forEach(g => {
const i1 = teams.indexOf(g.t1);
const i2 = teams.indexOf(g.t2);
matrix[i1][i2] = g.s1 + g.se1 + g.sp1;
matrix[i2][i1] = g.s2 + g.se2 + g.sp2;
}, []);
return matrix;
},
};

@ -0,0 +1,2 @@
const UI = {
};
Loading…
Cancel
Save