# Sensor with a sliding window (Chartist example)

> A new reading every second, and a line under the chart that says which elements each update kept, added and removed.

`src/main.ts`:

```ts
import 'chartist/styles.css';
import './style.css';
import { lineChart, type SceneNode } from 'chartist';
import { liveDomRenderer } from 'chartist/live';
import { firstReadings, onReading } from './readings';

const readout = document.querySelector('#changes')!;
const count = (node: SceneNode): number =>
  1 + node.children.reduce((sum, child) => sum + count(child), 0);

const chart = lineChart('#chart', firstReadings, {
  // Keep the SVG, and know each reading by its label.
  renderer: liveDomRenderer({ key: 'label' }),
  showArea: true,
  on: {
    // What each render did to the SVG's elements.
    mount: ({ scene, changes, cause }) => {
      const total = count(scene);
      if (cause === 'create') {
        readout.textContent = `Drew ${total} elements.`;
        return;
      }
      const tally = { add: 0, update: 0, remove: 0 };
      for (const change of changes) {
        tally[change.op] += 1;
      }
      readout.textContent =
        `Kept ${total - tally.add} of ${total} elements (${tally.update} changed), ` +
        `added ${tally.add}, removed ${tally.remove}.`;
    }
  }
});

// A new reading every second: the oldest one goes, the new one comes.
onReading(data => chart.update({ data }));
```

`index.html`:

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="module" src="/src/main.ts"></script>
  </head>
  <body>
    <div id="chart" class="ct-golden-section"></div>
    <p id="changes"></p>
  </body>
</html>
```

`src/readings.ts`:

```ts
// A temperature sensor that reports every second. The readings come from
// a seeded generator, so every run shows the same ones.

let seed = 42;
const random = () => {
  seed = (seed * 16807) % 2147483647;
  return (seed - 1) / 2147483646;
};

let data = {
  labels: ['1s', '2s', '3s', '4s', '5s', '6s', '7s', '8s', '9s', '10s'],
  series: [[21.2, 21.4, 21.3, 21.7, 21.9, 21.8, 22.1, 22, 22.3, 22.2]]
};

/** The last ten readings. */
export const firstReadings = data;

/** Calls `listener` every second with the last ten readings. */
export function onReading(listener: (readings: typeof data) => void) {
  let second = 10;
  setInterval(() => {
    second += 1;
    const [values] = data.series;
    const next = values[values.length - 1] + random() - 0.5;
    const reading = Math.round(Math.min(23.5, Math.max(20.5, next)) * 10) / 10;
    // Drop the oldest reading and add the new one.
    data = {
      labels: [...data.labels.slice(1), `${second}s`],
      series: [[...values.slice(1), reading]]
    };
    listener(data);
  }, 1000);
}
```

`src/style.css`:

```css
#changes {
  margin: 0.5rem 0 0;
  font:
    0.8rem/1.4 ui-monospace,
    monospace;
  color: #6b6b6b;
}
```
