Top: a graph's past holds still — columns draw the peak of their own fixed slice of history
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
be0f2a5aaf
commit
ec94cb8bff
@@ -0,0 +1,41 @@
|
||||
// Which points of a curve does each dot-column of a graph draw?
|
||||
//
|
||||
// A curve holds up to `cap` points (the whole history window); a box is `cols` columns wide,
|
||||
// and a narrow one — the net graph, a phone — has fewer columns than points. Taking "the
|
||||
// nearest point" for each column draws one point in three and, worse, a *different* one in
|
||||
// three every time the curve advances: a spike is there, gone, there again, and the whole
|
||||
// graph reshapes once a second. So:
|
||||
//
|
||||
// - a column draws the PEAK of all the points that fall in it, so nothing is ever skipped; and
|
||||
// - columns are cut from the data, not from the box: point number `a` (counted since the page
|
||||
// opened, `advance` being the newest) always belongs to column ⌊a·cols/cap⌋, whatever has
|
||||
// arrived since. A finished column therefore never changes — the graph only ever slides
|
||||
// left by whole columns, and only its newest column is still moving.
|
||||
//
|
||||
// With more columns than points (a wide box) each point simply spans several columns.
|
||||
// Returns one value per column, oldest first, right-aligned: a young curve has fewer columns
|
||||
// than the box and draws in from the right.
|
||||
export function columnsOf(values: number[], advance: number, cap: number, cols: number): number[] {
|
||||
const n = Math.min(values.length, cap)
|
||||
if (n === 0 || cols < 1 || cap < 1) return []
|
||||
const at = (a: number) => values[values.length - 1 - (advance - a)] // the point numbered a
|
||||
const oldest = advance - n + 1
|
||||
const out: number[] = []
|
||||
if (cols >= cap) {
|
||||
const kLast = Math.ceil(((advance + 1) * cols) / cap) - 1
|
||||
for (let k = kLast - cols + 1; k <= kLast; k++) {
|
||||
const a = Math.floor((k * cap) / cols)
|
||||
if (a >= oldest && a <= advance) out.push(at(a))
|
||||
}
|
||||
return out
|
||||
}
|
||||
const kLast = Math.floor((advance * cols) / cap)
|
||||
for (let k = kLast - cols + 1; k <= kLast; k++) {
|
||||
const a0 = Math.max(oldest, Math.ceil((k * cap) / cols)), a1 = Math.min(advance, Math.ceil(((k + 1) * cap) / cols) - 1)
|
||||
if (a1 < a0) continue
|
||||
let peak = at(a0)
|
||||
for (let a = a0 + 1; a <= a1; a++) peak = Math.max(peak, at(a))
|
||||
out.push(peak)
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user