PRAXIS/Docs
Concepts

Rules & events

A rule binds a zone, an object class, and a trigger. When it fires, you get an event: a discrete, timestamped, countable fact about the scene.

Anatomy of a rule#

rule.json
{
  "id": "rule_gate_count",
  "zone": "zone_a",
  "classes": ["car", "van", "truck"],
  "trigger": "enter",
  "min_dwell_s": 0
}

Four triggers exist today:

TriggerFires when
enterAn object transitions from outside the zone to inside it
exitAn object that was inside leaves
dwellAn object stays inside longer than min_dwell_s
countContinuously; maintains a running total of distinct entries

What counts as inside#

The naive test, box center inside polygon, undercounts. A car can clip the corner of a zone with a third of its body and never put its center inside. Praxis instead samples a 5×5 grid across the object's box and requires at least 25% of the samples to land inside the zone's polygon for that frame. Entries register when a car is genuinely in the zone, including partial passes along an edge.

One car, one event#

The counting failure modes come in mirrored pairs, and both get handled explicitly:

  • Double counting. A track ID switch mid-crossing looks like two entries. Candidate duplicate events get merged, but only when their two tracks never coexist in the same frames. Coexistence proves two physical objects.
  • Undercounting. Two cars entering side by side at the same moment are the classic casualty of aggressive merging. The coexistence test keeps them separate: both tracks were alive simultaneously, so both entries stand.
This exact logic produces the Praxis number in the challenge. On the 15-second sample feed it registers 15 distinct entries, including two side-by-side pairs that most people miss on the first try.

The event payload#

event.json
{
  "id": "evt_9f2c",
  "type": "zone.entry",
  "rule": "rule_gate_count",
  "zone": "zone_a",
  "feed": "src_boulevard",
  "t": 7.307,
  "track": 41,
  "class": "car",
  "position": [0.626, 0.741],
  "evidence": {
    "crop": "/evidence/evt_9f2c/crop.jpg",
    "track_history": "/evidence/evt_9f2c/track.json",
    "zone_geometry": "/evidence/evt_9f2c/zone.json"
  }
}

Positions are normalized to frame size. The evidence block is not optional decoration; see Evidence for why every event carries it.