points = {
const start = active.length ? names.size : 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 = start;
for (const star of stars) {
const score = (scores[star.name] = (scores[star.name] || 0) + p);
points.push({
...star,
day,
points: 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;
}