/** * One-time generator: snapshot the all-time leaders from the legacy * `mw-leaders/{level}/games` collection and write them into app/legends.html as * a FULLY-RENDERED, static page — no runtime JS, no Firebase at page load. * * The data never changes, so the page is a frozen artifact. Re-run only if you * ever need to regenerate it. Because `firebase` is an app-workspace dependency, * run it so Node can resolve it, e.g. from the app directory: * (cd app && node ../scripts/export-legends.js) */ import { writeFileSync } from 'node:fs' import { resolve, dirname } from 'node:path' import { fileURLToPath } from 'node:url' import { initializeApp } from 'firebase/app' import { getFirestore, getDocs, collection, query, orderBy, limit } from 'firebase/firestore/lite' import { levels } from '../lib/levels.js' // Mirror of TimerService.pretty() (utils/timer/timer.js) — inlined so this // generator has no cross-module import chain to resolve under raw Node. const clean = (str, separator) => (str === '00' ? '' : `${str}${separator}`) const pretty = duration => { if (!duration) return undefined const milliseconds = parseInt((duration % 1000) / 100) const seconds = Math.floor((duration / 1000) % 60) const minutes = Math.floor((duration / (1000 * 60)) % 60) const hours = Math.floor((duration / (1000 * 60 * 60)) % 24) const hh = hours < 10 ? `0${hours}` : `${hours}` const mm = minutes < 10 ? `0${minutes}` : `${minutes}` const ss = seconds < 10 ? `0${seconds}` : `${seconds}` return `${clean(hh, ':')}${clean(mm, ':')}${clean(ss, '.')}${clean(milliseconds, '')}` } // Hardcoded for this one-time run (public, non-secret keys — access is governed // by Firestore rules). This is the project the deployed app has always used. const firebaseConfig = { apiKey: 'AIzaSyCTi_5Sm5dHFNf0d_Gn0MNWmlGheFBf6MQ', authDomain: 'moment-188701.firebaseapp.com', databaseURL: 'https://moment-188701.firebaseio.com', projectId: 'secure-moment-188701', storageBucket: 'secure-moment-188701.firebasestorage.app', messagingSenderId: '113827947104', appId: '1:113827947104:web:b176f746d8358302c51905', measurementId: 'G-LZRDY0TG46' } console.log(`Exporting Legends from project: ${firebaseConfig.projectId}`) const TOP_N = 10 const escapeHtml = str => String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') const app = initializeApp(firebaseConfig) const store = getFirestore(app) const sections = [] for (const id of Object.keys(levels)) { const q = query( collection(store, 'mw-leaders', id, 'games'), orderBy('time'), limit(TOP_N) ) const snapshot = await getDocs(q) const rows = snapshot.docs.map(d => { const data = d.data() return { name: data.name || 'Anonymous', time: data.time } }) console.log(`${id}: ${rows.length} record(s)`) const items = rows.map((r, i) => `
Epic scores — the top times set before version 1.0.