function main() {
  const r = $data.current;
  const source = $data.history;
  const series = [];
  let run = [], previousTime = null;
  for (const p of source) {
    const age = p.elapsed !== null && r.elapsed !== null
      ? p.elapsed - r.elapsed : (p.timestamp - r.timestamp) / 1000;
    if (p.speed === null || age < -30 || age > 0 ||
        (previousTime !== null && p.timestamp - previousTime > 1000)) {
      if (run.length) series.push(run);
      run = [];
    }
    if (p.speed !== null && age >= -30 && age <= 0) run.push({age, speed:p.speed});
    previousTime = p.timestamp;
  }
  if (run.length) series.push(run);
  const topSpeed = Math.max(60, ...source.map(p => p.speed ?? 0));
  return <CardContent title="最近 30 秒" trailing={r.speedUnit} renderer={m => {
    const w = Math.max(1,$env.width-m.supportedGapLeft-m.supportedGapRight);
    const h = Math.max(1,$env.height-m.headerHeight-m.supportedGapTop-m.supportedGapBottom-18);
    return <Group width={w} height={h+18}>
      <Line width={w} height={h} x1={0} y1={h} x2={w} y2={h}
        stroke={$env.foreground} opacity={0.2} lineWidth={1}/>
      {series.map((run,i) => <Polyline key={'segment'+i} width={w} height={h}
        points={run.map(p => [(p.age+30)/30*w, h-Math.min(1,p.speed/topSpeed)*h])}
        fill="clear" stroke={$env.accent} lineWidth={2}/>) }
      <Text x={0} y={h+3} width={40} height={12} fontSize={9}
        alignment="leading" color={$env.foreground}>−30 s</Text>
      <Text x={w-36} y={h+3} width={36} height={12} fontSize={9}
        alignment="trailing" color={$env.foreground}>现在</Text>
      {source.length === 0 ? <Text width={w} height={h} fontSize={12}
        color={$env.foreground}>暂无历史采样</Text> : null}
    </Group>;
  }}/>;
}
