{#- A series drawn and listed (ADR-0092, as ADR-0096 and ADR-0097 amend it): the curves of its measures, drawn on the server as SVG with no script of its own, and its readings as a table. A node's page shows the curves that stand on it (`_node_facts.html`); its Series view every curve at or beneath it and the newest `reading_cap` rows of each series they were drawn from; its History page every row and no curve. The geometry is `little_sister.curves`' — every number below is its, and this only writes it down. What is drawn, and what says so in words: * the value axis — a hairline per step, its reading on the left, and a free-text unit once above the plot; a span or a size unit names itself in every step instead; * the line, broken wherever a reading failed, answered without a number, or nothing was read for longer than the node's freshness tolerance, and a dot for a reading that stands alone between two breaks and for the newest one; * a reading that failed — its record carries an `error` — marked at its instant in the lane beneath the baseline, never as a zero, and counted beside the title with the mark as its key; a hole is counted too, and has no mark of its own; * the time axis, beneath the plot and a drawing of its own: labels at round times in the configured zone, a faint line for each across the plot, and on a Series view a track divided at the labels, each stretch between two of them a link to the view over it that returns to the curve's group — in the tab order on the view's first curve alone, since every curve's are the same links (ADR-0098 decisions 3 and 4) — the oldest and the newest time where no round time falls between them; * each reading's time and value where the pointer is, as a title and with nothing drawn: the plot is cut between each two neighbors' midpoints, so the pointer finds a time, not a line — or, where a window holds more readings than the plot has columns, each column's range, count and times (ADR-0098 decision 5). On a Series view the plot says where its window stands on it (`data-left`, `data-right`) and how tall its strips run, for the view's script, which draws a drag's stretch and one line across every plot and reads the strips' titles into the summaries (decision 6). A plot **of runs** (ADR-0106 decision 5, ADR-0111) has marks in place of a line: a stem from the baseline for each run, under a measure to its value and without one to the height its verdict gives a tick, all of one verdict as one path, the worse painted over the better — no verdict, passed, warned, failed — and then the heads in that order: a filled dot for a run that passed, where it has room; the warning's triangle; a hollow ring in the failure ink. The lane marks each column that holds a run that failed, and the summary counts the runs and then what did not pass, by kind, each with its mark as its key. `role="img"` keeps the per-reading titles from being read out one by one: the table is the accessible twin, and the caption says what the drawing shows. -#} {%- from '_status_cue.html' import status_cue %} {#- What a Series view says of a node none of whose series draws a curve (ADR-0106 decision 4): how many readings it keeps, and where they are. Whose they are, where they are a subject's that has no node of its own — its line shares a node, or its node was removed (ADR-0109 decision 6) — so that a removed subject's kept readings do not read as its check's: by name, the first three and how many more. -#} {%- macro quiet_line(one) -%}

{{ one.path }} keeps {{ one.kept }} {{ "reading" if one.kept == 1 else "readings" }} {%- if one.unstood -%} {%- if one.unstood_kept < one.kept %}, {{ one.unstood_kept }} of them{% endif %} of {% for subject in one.unstood[:3] -%} {{ subject }}{{ "" if loop.last else " and " if loop.revindex == 2 and one.unstood | length <= 3 else ", " }} {%- endfor -%} {%- if one.unstood | length > 3 %} and {{ one.unstood | length - 3 }} more{% endif -%} , which {{ "has no node of its own" if one.unstood | length == 1 else "have no node of their own" }}, {%- elif one.subjects > 1 %} of {{ one.subjects }} subjects {%- endif %} and draws no curve — they are on its History page.

{%- endmacro %} {%- macro runs_summary(c) -%} {%- if c.readings == 0 -%} no runs in this window {%- else -%} {{ c.readings }} {{ "run" if c.readings == 1 else "runs" }} {%- if c.lowest %} · newest {{ c.newest }} · lowest {{ c.lowest }} · highest {{ c.highest }}{% endif -%} {%- if c.failed %} · {{ c.failed }} failed{% endif -%} {%- if c.warned %} · {{ c.warned }} warned{% endif -%} {%- if c.unjudged %} · {{ c.unjudged }} without a verdict{% endif -%} {%- endif -%} {%- endmacro %} {%- macro summary(c) -%} {%- if c.of_runs -%} {{ runs_summary(c) }} {%- else -%} {%- if c.readings == 0 and c.first -%} no readings in this window {%- elif not c.valued -%} no values in this window {%- endif -%} {%- if c.lowest -%} newest {{ c.newest }} · lowest {{ c.lowest }} · highest {{ c.highest }} {%- endif -%} {%- if c.failed -%} {%- if c.lowest or not c.valued %} · {% endif -%} {{ c.failed }} failed {%- endif -%} {%- if c.holes %} · {{ c.holes }} {{ "stretch" if c.holes == 1 else "stretches" }} without readings{% endif -%} {%- endif -%} {%- endmacro %} {#- A curve seen small (ADR-0114): the plot of `curve` below with nothing around it — its box is the plot's own, from the top of the scale to the baseline, so the line is the curve's line on the curve's scale, from zero, broken where the curve breaks — squeezed into a strip that sits in a line of text. The strokes keep their width whatever the squeeze. A reading that stands alone is a stroke of no length, which a round cap makes a dot; a run is its stem. It says nothing by itself: the words beside it do, so it is hidden from a reader that hears the page. -#} {%- macro spark(c) -%} {%- endmacro %} {%- macro curve(c, zoom=none, times=none, anchor="", keyed=true) -%}
{{ c.label }} {{ summary(c) }}
{%- for tick in c.ticks %} {{ tick.text }} {%- endfor %} {%- for t in c.time_ticks %} {%- endfor %} {%- if c.unit_label %} {{ c.unit_label }} {%- endif %} {%- if c.of_runs and not c.ticks %} {%- endif %} {%- for d in c.paths %} {%- endfor %} {%- for verdict in ("unjudged", "passed", "warned", "failed") %} {%- set d = c.stem_path(verdict) %} {%- if d %} {%- endif %} {%- endfor %} {%- for stem in c.heads("passed") %} {%- endfor %} {%- for stem in c.heads("warned") %} {%- endfor %} {%- for stem in c.heads("failed") %} {%- endfor %} {%- for dot in c.dots %} {%- endfor %} {%- if c.end and c.end not in c.dots %} {%- endif %} {%- for mark in c.marks %} {%- endfor %} {%- for strip in c.hover %} {{ strip.title }} {%- endfor %}
{%- endmacro %} {#- The readings, newest first, as the ADR lists a row: the time on the series' clock with the code the reading stood with as a cue beside it, a column per field as the record list writes it, and the sentence as it stood. The table is a box that scrolls both ways inside itself, its heading row and its Time column held still, as wide as the page and about as tall as the window, every reading in it — a region with a name and a place in the tab order, so a keyboard can scroll it (ADR-0102 decision 1). The cue rides in the Time cell so that one column holds still rather than two: a second needs the first's width, which the time format decides. A column a measure declares is headed by its label and unit over the field's name, a label that is the field's name standing once with the unit beside it; any other by the field's name; the declared ones first (decision 2). -#} {%- macro readings_table(view) -%}
{%- for column in view.columns %} {%- endfor %} {%- for row in view.rows %} {%- for column in view.columns %} {%- set field = row.fields.get(column.field) %} {%- endfor %} {%- endfor %}
Time {%- if column.label %}{{ column.label }}{% if column.unit %} · {{ column.unit }}{% endif %} {{ column.field }} {%- else %}{{ column.field }}{% if column.unit %} · {{ column.unit }}{% endif %} {%- endif %}Reason
{% if row.code %} {{ status_cue(row.code, labeled=true) }}{% endif %}{% if field %}{% if field.kind == 'instant' %}{% else %}{{ field.text }}{% endif %}{% endif %}{{ row.texts | join('; ') | markdown_inline }}
{%- endmacro %}