import type { EstimateResult } from '../estimate' import { isoDate } from '../format' import type { Filters, WebStateInfo } from '../types' interface Props { result: EstimateResult filters: Filters state: WebStateInfo } const W = 820 const H = 320 const PAD = { top: 16, right: 20, bottom: 36, left: 48 } interface Point { day: number games: number } /** Build the cumulative "games finished by day N" curve for the basis. */ function buildPoints(props: Props): Point[] { const { result, filters, state } = props const rows = [...result.included].sort((a, b) => a.lengthHours - b.lengthHours) const pts: Point[] = [] if (filters.basis === 'pace') { const pace = state.pace_games_per_day if (pace <= 0) return [] rows.forEach((_, i) => pts.push({ day: (i + 1) / pace, games: i + 1 })) return pts } let cum = 0 rows.forEach((r, i) => { cum += r.lengthHours pts.push({ day: cum / filters.dailyHours, games: i + 1 }) }) return pts } function dayToDate(day: number): string { const d = new Date() d.setDate(d.getDate() + Math.round(day)) return isoDate(d) } export function TimelineChart(props: Props) { const pts = buildPoints(props) if (pts.length < 2) { return (
Not enough games in scope to draw a timeline.
Cumulative games finished over time (shortest games first).