Published
Edited
May 17, 2020
1 fork
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
contestantSummarys = {
const map = d3.rollup(pastEvents,
events => ({
contestant: events[0].contestant,
name: events[0].name,
elapsedTotal: d3.pairs(d3.extent(events.map(e => e.timestamp)), (a, b) => b - a)[0],
latestCheckpoint: d3.max(events.map(e => e.checkpoint)),
events,
timestamps: events.map(e => e.timestamp),
deltas: d3.pairs(events, (a, b) => b.timestamp - a.timestamp),
}),
e => e.contestant);

// Sort by least time at last common check point
const contestantSummarys = Array.from(map).map(([_, d]) => ({
...d,
checkpointSegments: d3.pairs(d3.cumsum([0, ...d.deltas]))
}));
contestantSummarys.sort((a, b) => {
const i = Math.min(a.latestCheckpoint, b.latestCheckpoint);
return (a.timestamps[i] - a.timestamps[0]) - (b.timestamps[i] - b.timestamps[0]);
});
contestantSummarys.forEach((d, i) => d.rank = i + 1);
return contestantSummarys;
}
Insert cell
Insert cell
series = d3.stack()
.keys(checkpoints)
.value((contestantSummary, key) => contestantSummary.deltas[key])
(contestantSummarys)
.map((d, i) => (d.forEach(v => {
v.key = d.key;
}), d))
Insert cell
Insert cell
Insert cell
y = d3.scaleBand()
.domain(contestantSummarys.map(d => d.rank))
.range([margin.top, height - margin.bottom])
.padding(0.08)
Insert cell
color = color1
Insert cell
color1 = d3.scaleOrdinal()
.domain(series.map(d => d.key))
.range(d3.schemeSpectral[10])
.unknown("#ccc")
Insert cell
color2 = d3.scaleOrdinal()
.domain(checkpoints)
.range(checkpoints.map(v => d3.interpolateRainbow(v / (checkpoints.length - 1))))
.unknown("#ccc")
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${margin.top})`)
.call(d3.axisTop(x)
.ticks(width / 100, "s")
//.ticks(10)
.tickFormat(milliseconds => `${Math.round(milliseconds / 60 / 1000)}m`)
)
.call(g => g.selectAll(".domain").remove())
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).tickSizeOuter(0))
.call(g => g.selectAll(".domain").remove())
Insert cell
formatValue = x => isNaN(x) ? "N/A" : x.toLocaleString("en")
Insert cell
height = contestantSummarys.length * 25 + margin.top + margin.bottom
Insert cell
margin = ({top: 30, right: 200, bottom: 0, left: 30})
Insert cell
Insert cell
Insert cell
Insert cell
import {legend} from "@d3/color-legend"
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