// The club feed page. Server-rendered, self-contained: no external requests, // system fonts only, matching the rest of pds.js. /** * @param {string} s */ const esc = (s) => String(s) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"'); /** @param {number} meters */ const km = (meters) => (meters / 1000).toFixed(1); /** @param {number} seconds */ function duration(seconds) { const h = Math.floor(seconds / 3600); const m = Math.floor((seconds % 3600) / 60); const s = seconds % 60; const ms = `${String(m).padStart(h ? 2 : 1, '0')}:${String(s).padStart(2, '0')}`; return h ? `${h}:${ms}` : ms; } /** @param {number} meters @param {number} seconds */ function pace(meters, seconds) { const secPerKm = seconds / (meters / 1000); const m = Math.floor(secPerKm / 60); const s = Math.round(secPerKm % 60); return `${m}:${String(s).padStart(2, '0')}/km`; } /** @param {string} iso */ function dayLabel(iso) { return new Date(iso).toLocaleDateString('en-US', { weekday: 'short' }); } /** * @param {Object} feed * @param {string} feed.clubName * @param {string} feed.space * @param {Array<{did: string, handle: string, rev: string, hashHex: string, runs: Array<{startedAt: string, distanceMeters: number, durationSec: number, note: string}>}>} feed.members * @returns {string} */ export function renderFeedPage({ clubName, space, members }) { const totalMeters = members .flatMap((m) => m.runs) .reduce((sum, r) => sum + r.distanceMeters, 0); const maxMeters = Math.max( ...members.map((m) => m.runs.reduce((sum, r) => sum + r.distanceMeters, 0)), 1, ); // The lane board: each member is a track lane, bar length is their share of // the week's distance. Sorted like a results board, most distance first. const lanes = members .map((m) => ({ ...m, meters: m.runs.reduce((sum, r) => sum + r.distanceMeters, 0), })) .sort((a, b) => b.meters - a.meters) .map( (m, i) => `
This week the club ran ${km(totalMeters)} km together.
Each member's repo was pulled from their own PDS and verified before rendering: the commit's MAC, and the records against its set hash.
${receipts}