Public
Edited
Feb 14
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
layout = {
let size = 600;
let rot = 72;
let arc_width = 20;
let r = size / 2 - arc_width;
let r_in = r - arc_width;
let r_out = r + arc_width;
let arc1 = d3.arc().innerRadius(r_in).outerRadius(r);
let arc2 = d3.arc().innerRadius(r).outerRadius(r_out);
let ribbon = d3.ribbon().radius(r_in);
let scale = d3
.scaleLinear()
.domain([-1, 1])
.range([-size / 2, size / 2]);
let team_colors = d3
.scaleOrdinal()
.domain(d3.range(14))
.range(teams.map((d) => d.colors));
let chords = d3.chord().padAngle(0.05)(M);

return { chords, arc1, arc2, ribbon, scale, size, team_colors, rot };
}
Insert cell
// The old *score* matrix that used just total points scored by i against j
// M = {
// let M = [];
// for (let i = 0; i < teams.length; i++) {
// let row = [];
// for (let j = 0; j < teams.length; j++) {
// let games_ij = games.filter((o) => o.idx1 == i && o.idx2 == j);
// let points_i_over_j = d3.sum(games_ij, (o) => o.score1);
// let games_ji = games.filter((o) => o.idx1 == j && o.idx2 == i);
// let points_i_under_j = d3.sum(games_ji, (o) => o.score2);
// row.push(points_i_over_j + points_i_under_j);
// }
// M.push(row);
// }
// return M;
// }
Insert cell
M = {
let M = [];
for (let i = 0; i < teams.length; i++) {
let row = [];
for (let j = 0; j < teams.length; j++) {
if (i != j) {
let games_ij = games.filter((o) => o.idx1 == i && o.idx2 == j);
let wins_ij = games_ij.filter((o) => o.score1 > o.score2).length;
let points_i_over_j = d3.sum(games_ij, (o) => o.score1);
let points_j_under_i = d3.sum(games_ij, (o) => o.score2);
let games_ji = games.filter((o) => o.idx1 == j && o.idx2 == i);
let points_j_over_i = d3.sum(games_ji, (o) => o.score1);
let points_i_under_j = d3.sum(games_ji, (o) => o.score2);
let points_i_against_j = points_i_over_j + points_i_under_j;
let total_points_ij =
+points_i_over_j +
points_j_under_i +
points_j_over_i +
points_i_against_j;
row.push(wins_ij + points_i_against_j / total_points_ij);
} else {
row.push(0);
}
}
M.push(row);
}
return M;
}
Insert cell
teams = _.uniq(games.map((o) => [o.name1, o.name2]).flat())
.sort()
.map(function (team) {
if (team == "Campbell") {
return {
team,
colors: ["#EA7125", "#1E252B"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/8/84/Campbell_Fighting_Camels_logo.svg"
};
} else if (team == "Charleston_So") {
return {
team,
colors: ["#A8996E", "#002855"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/8/86/Charleston_Southern_Buccaneers_logo.svg"
};
} else if (team == "Gardner_Webb") {
return {
team,
colors: ["#BB0000", "#141414"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/a/a3/Gardner%E2%80%93Webb_Runnin%27_Bulldogs_logo.svg"
};
} else if (team == "High_Point") {
return {
team,
colors: ["#330072", "#818183"],
logo_url:
"https://upload.wikimedia.org/wikipedia/commons/2/2c/High_Point_Panthers_logo.svg"
};
} else if (team == "Longwood") {
return {
team,
colors: ["#041e42", "#9ea2a2"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/5/5f/Longwood_Lancers_logo.svg"
};
} else if (team == "Presbyterian") {
return {
team,
colors: ["#0060A9", "#9D2235"],
logo_url:
"https://upload.wikimedia.org/wikipedia/commons/9/93/Presbyterian_College_logo.svg"
};
} else if (team == "Radford") {
return {
team,
colors: ["#c2011b", "#d1d3d4"],
logo_url:
"https://upload.wikimedia.org/wikipedia/commons/6/6d/Radford_Highlanders_logo.png"
};
} else if (team == "SC_Upstate") {
return {
team,
colors: ["#00703c", "#000000"],
logo_url:
"https://upload.wikimedia.org/wikipedia/commons/8/8e/USC_Upstate_Spartans_logo.svg"
};
} else if (team == "UNC_Asheville") {
return {
team,
colors: ["#003DA5", "#FFFFFF"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/9/93/UNC_Asheville_Bulldogs_logo.svg"
};
} else if (team == "Winthrop") {
return {
team,
colors: ["#660000", "#F0B323"],
logo_url:
"https://upload.wikimedia.org/wikipedia/en/d/df/Winthrop_Eagles_logo.svg"
};
}
})
Insert cell
function team_info(name) {
let wins = games.filter((o) => o.name1 == name);
let losses = games.filter((o) => o.name2 == name);
let points = d3.sum(wins, (o) => o.score1) + d3.sum(losses, (o) => o.score2);
let points_against =
d3.sum(wins, (o) => o.score2) + d3.sum(losses, (o) => o.score1);

let div = d3
.create("div")
.style("background", "rgba(255,255,255,0.5)")
.style("border", "solid 1px lightslategray")
.style("border-radius", "4px")
.style("font-size", "0.8em");
div
.append("div")
.style("text-decoration", "underline")
.style("font-weight", "bold")
.text(name.replace(/_/g, " "));
let ul = div.append("ul").style("margin-top", "0px");
ul.append("li").text(`Record: ${wins.length}-${losses.length}`);
ul.append("li").text(
`Points: ${d3.sum(wins, (o) => o.score1) + d3.sum(losses, (o) => o.score2)}`
);
ul.append("li").text(
`Points against: ${
d3.sum(wins, (o) => o.score2) + d3.sum(losses, (o) => o.score1)
}`
);

return div.node();
}
Insert cell
function game_info(name1, name2) {
let div = d3
.create("div")
.style("background", "rgba(255,255,255,0.7)")
.style("border", "solid 1px lightslategray")
.style("border-radius", "4px")
.style("width", "250px");
let games_1_over_2 = games
.filter((o) => o.name1 == name1 && o.name2 == name2)
.map((o) => Object.assign({}, o));
games_1_over_2.forEach(function (g) {
g.first_team = name1;
g.first_score = g.score1;
g.second_team = name2;
g.second_score = g.score2;
});
let games_2_over_1 = games
.filter((o) => o.name1 == name2 && o.name2 == name1)
.map((o) => Object.assign({}, o));
games_2_over_1.forEach(function (g) {
g.first_team = name1;
g.first_score = g.score2;
g.second_team = name2;
g.second_score = g.score1;
});

let these_games = d3.sort(
games_1_over_2.concat(games_2_over_1),
(o) => o.date
);
let table = div.append("table");
let header = table.append("tr");
header.append("th"); // .style("width", "2000px");
header.append("th").text(name1.replace(/_/g, " "));
header.append("th").text(name2.replace(/_/g, " "));
these_games.forEach(function (game) {
let row = table.append("tr");
row
.append("td")
// .style("width", "2000px")
.text(d3.timeFormat("%b %d, '%y")(game.date));
row.append("td").style("text-align", "center").text(game.first_score);
row.append("td").style("text-align", "center").text(game.second_score);
});

return div.node();
}
Insert cell
games = FileAttachment("big_south_games@4.csv").csv({ typed: true })
Insert cell
tippy_style = html`<link style="display: none" rel="stylesheet" href="${await require.resolve(
`tippy.js/themes/light-border.css`
)}">`
Insert cell
tippy = require("tippy.js@6")
Insert cell
math = require("mathjs")
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more