Advanced rules
Beyond per-field settings, a survey type can carry three kinds of record-level rule. They are edited in the Advanced rules panel at the bottom of the survey builder and validated when you save, so a malformed rule is never stored. Each section has a point-and-click editor by default, and an Edit as JSON toggle for the exact shape or for the rare edge case the visual editor does not cover.
Validation checks
Section titled “Validation checks”A check is a rule across the whole record: a comparison between two values, where each value is a field, a number, or an aggregate over a repeat group (a sum of a sub-field, or a count of entries). The check holds when the comparison is true; otherwise the record gets your message, as an error or a warning.
In the visual editor each check reads left to right: pick a value, a comparison (=, not equal, at most, less than, at least, greater than), and another value, then type a plain-language message and choose Error (blocks save) or Warning (flags only). The field dropdowns come from the survey’s own fields, and “compare to another field” is a peer of “compare to a number.”
Use checks for things a single field cannot express:
- A repeat group must total a fixed number (for example, a set of counts must sum to 20).
- One field must be at or below another (a start at or before an end).
- A count must be within bounds.
The same rule, shown by the Edit as JSON toggle:
[ { "key": "counts_total", "message": { "en": "The counts must total 20." }, "left": { "sum": { "repeat": "rows", "field": "count" } }, "op": "eq", "right": { "const": 20 } }]A check whose values cannot be resolved yet (a field is still empty) is skipped, so incomplete data never
fails. The JSON view also exposes a when condition (evaluate a check only in certain cases) and a field (to
attach the message to a field).
A rule that must not happen
Section titled “A rule that must not happen”Besides comparing two values, a check can fail when a condition matches, which is the way to express a “these two things must not both be true” rule that a comparison cannot. For example, a specimen may keep an aging structure sample or carry a tag, but not both.
This “prohibition” form is written with the Edit as JSON toggle (the visual editor covers comparisons). It looks like this:
[ { "key": "structure_or_tag", "message": { "en": "A specimen keeps its structure sample or carries a tag, never both." }, "failWhen": { "all": [ { "field": "structure_no", "op": "not_empty" }, { "field": "tag_no", "op": "not_empty" } ] } }]The check fails when every part of failWhen holds. Set severity to error or warning like any check.
When a check sums or counts over a repeat group, the sub-field it names is checked when you save, so a typo in the summed field is caught then rather than becoming a rule that silently never fires.
Computed fields
Section titled “Computed fields”A computed field is filled by the engine from other fields instead of being entered. It is read-only on the form and stored with the record, so reports, export, and checks all see the value.
In the visual editor you pick a number field to make computed, then build its value by choosing a function: a field, a number, a total or count over a list, a duration between two time fields, or a formula (a +−×÷ b, where each side is itself an expression). The dropdowns are filtered to compatible fields, so a duration only offers date or time fields and a total only offers numeric sub-fields.
The same expression as JSON (the key is an existing field’s key; that field becomes computed):
{ "soak_hours": { "duration": { "from": "set_at", "to": "haul_at", "unit": "hours" } } }A computed value updates live as you fill the fields it depends on.
Sub-sampling plans
Section titled “Sub-sampling plans”A sub-sampling plan decides which records to select for extra sampling, at a rate that can vary by group (area, season, species, size class). This is something most field tools cannot do, because it needs a running count across records, which CensusIO keeps even offline.
In the visual editor you add a plan, give it a name, and pick a Method: every Nth record (systematic), a random probability per record (random sample), a quota per group (fixed count), all records (every unit), or take-what-you-can (opportunistic). The rate field changes to match the method (a percent, a 1-in-N interval, or a per-group quota). A Seed makes the selection identical across devices. Vary the rate by adds group dimensions from the survey’s fields (numeric ones can be split into bins, such as 5 cm length classes), and a rate overrides table sets a different rate for specific groups. You can also turn on specimen numbering (prefix, start, end, padding) and restart counting at each parent record.
The same plan as JSON:
[ { "key": "subsample", "label": { "en": "Sub-sample" }, "strategy": "systematic", "rate": 3, "seed": "subsample-2025", "stratum": { "keys": [{ "field": "species" }] } }]During entry the form shows the live decision (selected, a selection coming up, or not selected) and a specimen number when one is configured. The decision is stored with the record so sampling rates can be applied in analysis.