Elo trajectories: a century of strength on every team page
buildRatings samples each WC team's rating along the full walk (yearly historically, monthly since 2022) into elohistory.json (~72KB, 48 teams). Team pages plot it as a clean SVG line with year and rating gridlines — Germany's century, 1908 → today, in one glance. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,19 @@ function main(): void {
|
||||
let sxy = 0, sxx = 0; // regression of goal-diff on effective Elo diff
|
||||
const calib: { d: number; h: number; a: number }[] = [];
|
||||
|
||||
// Per-WC-team Elo trajectories: one sample per year historically, one per
|
||||
// month for the recent window — small enough to serve, rich enough to plot.
|
||||
const wcSet = new Set(ALL_TEAMS);
|
||||
const RECENT_FROM = '2022-01-01';
|
||||
const history = new Map<string, Map<string, number>>(); // team → periodKey → rating
|
||||
const sample = (team: string, date: string, rating: number): void => {
|
||||
if (!wcSet.has(team)) return;
|
||||
const key = date >= RECENT_FROM ? date.slice(0, 7) : date.slice(0, 4);
|
||||
let m = history.get(team);
|
||||
if (!m) { m = new Map(); history.set(team, m); }
|
||||
m.set(key, Math.round(rating));
|
||||
};
|
||||
|
||||
let lastDate = '';
|
||||
for (const r of rows) {
|
||||
const home = canonicalTeam(r.home);
|
||||
@@ -98,6 +111,8 @@ function main(): void {
|
||||
const fastDelta = eloDelta(r.hs, r.as, feh, fea, k * FAST_M, homeAdv);
|
||||
eloFast.set(home, feh + fastDelta);
|
||||
eloFast.set(away, fea - fastDelta);
|
||||
sample(home, r.date, eh + delta);
|
||||
sample(away, r.date, ea - delta);
|
||||
lastDate = r.date;
|
||||
}
|
||||
|
||||
@@ -202,6 +217,14 @@ function main(): void {
|
||||
mkdirSync(OUT_DIR, { recursive: true });
|
||||
writeFileSync(join(OUT_DIR, 'ratings.json'), JSON.stringify(out));
|
||||
|
||||
// Per-team Elo trajectories for the team pages.
|
||||
const eloHistory: Record<string, [string, number][]> = {};
|
||||
for (const [team, m] of history) {
|
||||
eloHistory[team] = [...m.entries()].sort((a, b) => a[0].localeCompare(b[0]));
|
||||
}
|
||||
writeFileSync(join(OUT_DIR, 'elohistory.json'), JSON.stringify({ recentFrom: RECENT_FROM, teams: eloHistory }));
|
||||
console.log(`elo history → public/data/elohistory.json (${Object.keys(eloHistory).length} teams)`);
|
||||
|
||||
// Compact training rows for the server's nightly in-tournament Team-DC refit
|
||||
// (absolute dates, so daysAgo can be recomputed as the tournament progresses).
|
||||
const dcRows = rows
|
||||
|
||||
Reference in New Issue
Block a user