Public
Edited
Nov 22, 2022
1 fork
2 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
names = new Set(
Object.values(data.members)
.filter(d => d.last_star_ts)
.map(d => d.name)
)
Insert cell
domains = ({
score: [0, Object.keys(data.members).length * 25 * 2],
days: [
...(function*() {
for (let d = 1; d <= 25; d++)
for (const s of [1, 2]) yield [dayFormat(d), s].join(',');
})()
],
time: [new Date(year, 11, 1), new Date(year, 11, 31)]
})
Insert cell
points = {
const start = Object.keys(data.members).length,
points = [],
scores = {};

for (const [day, stars] of Object.entries(days).sort((a, b) =>
a[0].localeCompare(b[0])
)) {
stars.sort((a, b) => a.ts - b.ts);
const missing = new Set(names);
const fastest = stars[0].ts;
let p = day.startsWith(' 1,') ? 0 : start;
for (const star of stars) {
const score = (scores[star.name] = (scores[star.name] || 0) + p);
points.push({
...star,
day,
points: day.startsWith(' 1,') ? 0 : p--,
score,
minutes: (star.ts - fastest) / 1000 / 60
});
missing.delete(star.name);
}
for (const name of missing) {
points.push({
name,
day,
incomplete: true,
points: 0,
score: scores[name],
minutes: Infinity
});
}
let rank = 1;
for (const p of points
.slice(points.length - names.size)
.sort((a, b) => b.score - a.score))
p.rank = rank++;
}

for (const last of d3
.rollup(
points.filter(d => !d.incomplete),
d => d[d.length - 1],
d => d.name
)
.values())
last.last = true;

return points;
}
Insert cell
scores_by_time = {
// `points` sorts points cumulatively by problem, but we need them by date for `score over time`
let score_by_name = {}, scores_by_time = []
let sortedPoints = points.filter(p => !p.incomplete).sort((a, b) => b.ts < a.ts ? 1 : -1)
for (const p of sortedPoints) {
score_by_name[p.name] = (score_by_name[p.name] || 0) + p.points
scores_by_time.push({...p, score: score_by_name[p.name]})
}
return scores_by_time
}
Insert cell
days = {
const days = {};
for (const member of Object.values(data.members)) {
for (const [day, parts] of Object.entries(member.completion_day_level)) {
for (const [part, result] of Object.entries(parts)) {
const key = [dayFormat(day), part];
days[key] = days[key] || [];
days[key].push({
name: member.name,
ts: new Date(result.get_star_ts * 1000)
});
}
}
}

return days;
}
Insert cell
data = (await fetch(`https://aoc-leaderboard-kl5s5a0sh-visnup.vercel.app?year=${year}&id=${owner}`)).json()
Insert cell
Insert cell
Insert cell
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