@trillboards/edge-core 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/centroidTracker.d.ts +107 -0
- package/dist/centroidTracker.d.ts.map +1 -0
- package/dist/centroidTracker.js +170 -0
- package/dist/centroidTracker.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* centroidTracker — ONE nearest-centroid tracker, for everything that needs one.
|
|
3
|
+
*
|
|
4
|
+
* ── WHY THIS FILE EXISTS ───────────────────────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Three independent implementations of "give this box the same id it had last
|
|
7
|
+
* frame" were in the tree, and they did not agree:
|
|
8
|
+
*
|
|
9
|
+
* edge-sensing FaceDetector.assignTrackingIds best-match, size-relative
|
|
10
|
+
* threshold, staleness pruning
|
|
11
|
+
* platform-web WebFaceDetector.assignFaceId FIRST match, fixed threshold,
|
|
12
|
+
* eviction by insertion order
|
|
13
|
+
* agent-core VehicleFlowProcessor.updateTracks (Kotlin — re-implements
|
|
14
|
+
* association scoring rather
|
|
15
|
+
* than calling the
|
|
16
|
+
* TrackAssociation.bestMatch
|
|
17
|
+
* sitting next to it)
|
|
18
|
+
*
|
|
19
|
+
* This is the TypeScript half consolidated onto the first one's algorithm, which
|
|
20
|
+
* is the only one of the three that is correct. The Kotlin pair is a different
|
|
21
|
+
* artifact with its own release cycle and is not touched here; the note above is
|
|
22
|
+
* so the next person does not make it a fourth.
|
|
23
|
+
*
|
|
24
|
+
* ── THE TWO DEFECTS THE WEB VERSION HAD ────────────────────────────────────
|
|
25
|
+
*
|
|
26
|
+
* 1. FIRST match, not BEST. It returned the first track inside the threshold
|
|
27
|
+
* rather than the closest, so with two people standing near each other the id
|
|
28
|
+
* that got assigned depended on Map insertion order. Two frames apart, the
|
|
29
|
+
* same two people could swap ids — and a swapped id is worse than a new one,
|
|
30
|
+
* because a new id is visibly a new person while a swap silently attributes
|
|
31
|
+
* one person's dwell to another.
|
|
32
|
+
*
|
|
33
|
+
* 2. Eviction by insertion order, not staleness. It dropped the OLDEST-INSERTED
|
|
34
|
+
* entry once the map passed 50 — which is the person who has been standing
|
|
35
|
+
* there longest, i.e. exactly the one a dwell metric cares about — while a
|
|
36
|
+
* track last seen an hour ago and re-inserted recently survived.
|
|
37
|
+
*
|
|
38
|
+
* Both are fixed by using this. The threshold also becomes size-relative
|
|
39
|
+
* (`max(w,h) * ratio`), which is what makes one constant work for a face filling
|
|
40
|
+
* the frame and a face across the room: a fixed pixel threshold is either too
|
|
41
|
+
* tight up close or too loose far away, and there is no value that is neither.
|
|
42
|
+
*
|
|
43
|
+
* ── WHAT THIS IS NOT ───────────────────────────────────────────────────────
|
|
44
|
+
*
|
|
45
|
+
* Not a motion model — no velocity, no prediction, no Kalman. It matches on
|
|
46
|
+
* position alone, so it holds an id across small movements between frames and
|
|
47
|
+
* loses it across an occlusion. That is sufficient for what consumes it today
|
|
48
|
+
* (per-frame face ids and dwell) and it is deliberately not more: a constant-
|
|
49
|
+
* velocity model and 512-d re-ID both already exist in `TrackAssociation.kt` and
|
|
50
|
+
* `TrackReId.kt`, and if this side ever needs them they should be ported, not
|
|
51
|
+
* reinvented here for a third time.
|
|
52
|
+
*/
|
|
53
|
+
export interface TrackedBox {
|
|
54
|
+
x: number;
|
|
55
|
+
y: number;
|
|
56
|
+
width: number;
|
|
57
|
+
height: number;
|
|
58
|
+
}
|
|
59
|
+
export interface TrackRecord {
|
|
60
|
+
id: number;
|
|
61
|
+
box: TrackedBox;
|
|
62
|
+
firstSeen: number;
|
|
63
|
+
lastSeen: number;
|
|
64
|
+
}
|
|
65
|
+
export interface CentroidTrackerOptions {
|
|
66
|
+
/**
|
|
67
|
+
* Match radius as a fraction of the detection's longest side.
|
|
68
|
+
*
|
|
69
|
+
* Size-relative on purpose — see the note above on why no fixed pixel value
|
|
70
|
+
* works at two distances.
|
|
71
|
+
*/
|
|
72
|
+
matchRatio?: number;
|
|
73
|
+
/** Drop a track not seen for this long. */
|
|
74
|
+
staleMs?: number;
|
|
75
|
+
/**
|
|
76
|
+
* Hard cap on retained tracks, evicted STALEST-FIRST.
|
|
77
|
+
*
|
|
78
|
+
* A safety valve for a pathological scene, not a working limit. Eviction order
|
|
79
|
+
* is the whole point: dropping the oldest-inserted entry removes the person
|
|
80
|
+
* who has been present longest, which is the one every dwell metric is about.
|
|
81
|
+
*/
|
|
82
|
+
maxTracks?: number;
|
|
83
|
+
}
|
|
84
|
+
export declare const DEFAULT_MATCH_RATIO = 0.5;
|
|
85
|
+
export declare const DEFAULT_STALE_MS = 2000;
|
|
86
|
+
export declare const DEFAULT_MAX_TRACKS = 256;
|
|
87
|
+
export declare class CentroidTracker {
|
|
88
|
+
private readonly tracks;
|
|
89
|
+
private readonly matchRatio;
|
|
90
|
+
private readonly staleMs;
|
|
91
|
+
private readonly maxTracks;
|
|
92
|
+
private nextId;
|
|
93
|
+
constructor(options?: CentroidTrackerOptions);
|
|
94
|
+
/**
|
|
95
|
+
* Assign ids to one frame's detections, in order.
|
|
96
|
+
*
|
|
97
|
+
* Returns one record per input box, same length and same order, so a caller
|
|
98
|
+
* can zip it against its own richer per-detection data.
|
|
99
|
+
*/
|
|
100
|
+
track(detections: TrackedBox[], now: number): TrackRecord[];
|
|
101
|
+
/** Live tracks, for callers that need to inspect state. */
|
|
102
|
+
active(): TrackRecord[];
|
|
103
|
+
reset(): void;
|
|
104
|
+
private pruneStale;
|
|
105
|
+
private enforceCap;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=centroidTracker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"centroidTracker.d.ts","sourceRoot":"","sources":["../src/centroidTracker.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAEH,MAAM,WAAW,UAAU;IACzB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,UAAU,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,mBAAmB,MAAM,CAAC;AACvC,eAAO,MAAM,gBAAgB,OAAQ,CAAC;AACtC,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAMtC,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkC;IACzD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,MAAM,CAAK;gBAEP,OAAO,GAAE,sBAA2B;IAMhD;;;;;OAKG;IACH,KAAK,CAAC,UAAU,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,EAAE;IAkE3D,2DAA2D;IAC3D,MAAM,IAAI,WAAW,EAAE;IAIvB,KAAK,IAAI,IAAI;IAKb,OAAO,CAAC,UAAU;IAMlB,OAAO,CAAC,UAAU;CAcnB"}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* centroidTracker — ONE nearest-centroid tracker, for everything that needs one.
|
|
4
|
+
*
|
|
5
|
+
* ── WHY THIS FILE EXISTS ───────────────────────────────────────────────────
|
|
6
|
+
*
|
|
7
|
+
* Three independent implementations of "give this box the same id it had last
|
|
8
|
+
* frame" were in the tree, and they did not agree:
|
|
9
|
+
*
|
|
10
|
+
* edge-sensing FaceDetector.assignTrackingIds best-match, size-relative
|
|
11
|
+
* threshold, staleness pruning
|
|
12
|
+
* platform-web WebFaceDetector.assignFaceId FIRST match, fixed threshold,
|
|
13
|
+
* eviction by insertion order
|
|
14
|
+
* agent-core VehicleFlowProcessor.updateTracks (Kotlin — re-implements
|
|
15
|
+
* association scoring rather
|
|
16
|
+
* than calling the
|
|
17
|
+
* TrackAssociation.bestMatch
|
|
18
|
+
* sitting next to it)
|
|
19
|
+
*
|
|
20
|
+
* This is the TypeScript half consolidated onto the first one's algorithm, which
|
|
21
|
+
* is the only one of the three that is correct. The Kotlin pair is a different
|
|
22
|
+
* artifact with its own release cycle and is not touched here; the note above is
|
|
23
|
+
* so the next person does not make it a fourth.
|
|
24
|
+
*
|
|
25
|
+
* ── THE TWO DEFECTS THE WEB VERSION HAD ────────────────────────────────────
|
|
26
|
+
*
|
|
27
|
+
* 1. FIRST match, not BEST. It returned the first track inside the threshold
|
|
28
|
+
* rather than the closest, so with two people standing near each other the id
|
|
29
|
+
* that got assigned depended on Map insertion order. Two frames apart, the
|
|
30
|
+
* same two people could swap ids — and a swapped id is worse than a new one,
|
|
31
|
+
* because a new id is visibly a new person while a swap silently attributes
|
|
32
|
+
* one person's dwell to another.
|
|
33
|
+
*
|
|
34
|
+
* 2. Eviction by insertion order, not staleness. It dropped the OLDEST-INSERTED
|
|
35
|
+
* entry once the map passed 50 — which is the person who has been standing
|
|
36
|
+
* there longest, i.e. exactly the one a dwell metric cares about — while a
|
|
37
|
+
* track last seen an hour ago and re-inserted recently survived.
|
|
38
|
+
*
|
|
39
|
+
* Both are fixed by using this. The threshold also becomes size-relative
|
|
40
|
+
* (`max(w,h) * ratio`), which is what makes one constant work for a face filling
|
|
41
|
+
* the frame and a face across the room: a fixed pixel threshold is either too
|
|
42
|
+
* tight up close or too loose far away, and there is no value that is neither.
|
|
43
|
+
*
|
|
44
|
+
* ── WHAT THIS IS NOT ───────────────────────────────────────────────────────
|
|
45
|
+
*
|
|
46
|
+
* Not a motion model — no velocity, no prediction, no Kalman. It matches on
|
|
47
|
+
* position alone, so it holds an id across small movements between frames and
|
|
48
|
+
* loses it across an occlusion. That is sufficient for what consumes it today
|
|
49
|
+
* (per-frame face ids and dwell) and it is deliberately not more: a constant-
|
|
50
|
+
* velocity model and 512-d re-ID both already exist in `TrackAssociation.kt` and
|
|
51
|
+
* `TrackReId.kt`, and if this side ever needs them they should be ported, not
|
|
52
|
+
* reinvented here for a third time.
|
|
53
|
+
*/
|
|
54
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
55
|
+
exports.CentroidTracker = exports.DEFAULT_MAX_TRACKS = exports.DEFAULT_STALE_MS = exports.DEFAULT_MATCH_RATIO = void 0;
|
|
56
|
+
exports.DEFAULT_MATCH_RATIO = 0.5;
|
|
57
|
+
exports.DEFAULT_STALE_MS = 2000;
|
|
58
|
+
exports.DEFAULT_MAX_TRACKS = 256;
|
|
59
|
+
function centre(b) {
|
|
60
|
+
return { cx: b.x + b.width / 2, cy: b.y + b.height / 2 };
|
|
61
|
+
}
|
|
62
|
+
class CentroidTracker {
|
|
63
|
+
constructor(options = {}) {
|
|
64
|
+
this.tracks = new Map();
|
|
65
|
+
this.nextId = 1;
|
|
66
|
+
this.matchRatio = options.matchRatio ?? exports.DEFAULT_MATCH_RATIO;
|
|
67
|
+
this.staleMs = options.staleMs ?? exports.DEFAULT_STALE_MS;
|
|
68
|
+
this.maxTracks = options.maxTracks ?? exports.DEFAULT_MAX_TRACKS;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Assign ids to one frame's detections, in order.
|
|
72
|
+
*
|
|
73
|
+
* Returns one record per input box, same length and same order, so a caller
|
|
74
|
+
* can zip it against its own richer per-detection data.
|
|
75
|
+
*/
|
|
76
|
+
track(detections, now) {
|
|
77
|
+
this.pruneStale(now);
|
|
78
|
+
// FRAME-LEVEL assignment, not per-detection greedy.
|
|
79
|
+
//
|
|
80
|
+
// Taking each detection in turn and giving it its own closest free track is
|
|
81
|
+
// ORDER-DEPENDENT, and the order it depends on is the detector's output
|
|
82
|
+
// order — which nothing controls. Measured on the two-person case: tracks at
|
|
83
|
+
// x=100 and x=140, next frame's boxes at x=125 and x=145.
|
|
84
|
+
//
|
|
85
|
+
// per-detection greedy, boxes in order 125 -> right(15), 145 -> left(45)
|
|
86
|
+
// per-detection greedy, boxes reversed 145 -> right(5), 125 -> left(25)
|
|
87
|
+
// minimum total distance 125 -> left(25), 145 -> right(5)
|
|
88
|
+
//
|
|
89
|
+
// So the forward order produces exactly the SWAP this class exists to
|
|
90
|
+
// prevent, and merely reversing the input fixes it. Scoring every candidate
|
|
91
|
+
// pair and consuming them shortest-first is order-independent and lands on
|
|
92
|
+
// the minimum-distance assignment here.
|
|
93
|
+
//
|
|
94
|
+
// It is a heuristic, not the optimum: shortest-first can be beaten by
|
|
95
|
+
// Hungarian on contrived layouts. That trade is deliberate — a subtly wrong
|
|
96
|
+
// O(n^3) implementation is worse than a correct heuristic, the seam is this
|
|
97
|
+
// one function if it ever needs to change, and what actually mattered was
|
|
98
|
+
// removing the dependence on input order.
|
|
99
|
+
const candidates = [];
|
|
100
|
+
detections.forEach((det, detIndex) => {
|
|
101
|
+
const { cx, cy } = centre(det);
|
|
102
|
+
const threshold = Math.max(det.width, det.height) * this.matchRatio;
|
|
103
|
+
for (const [trackId, track] of this.tracks) {
|
|
104
|
+
const c = centre(track.box);
|
|
105
|
+
const dist = Math.hypot(cx - c.cx, cy - c.cy);
|
|
106
|
+
if (dist < threshold)
|
|
107
|
+
candidates.push({ detIndex, trackId, dist });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
// Ties broken on trackId then detIndex so equal distances resolve the same
|
|
111
|
+
// way every run — Map iteration order must not decide an id.
|
|
112
|
+
candidates.sort((a, b) => a.dist - b.dist || a.trackId - b.trackId || a.detIndex - b.detIndex);
|
|
113
|
+
const assignment = new Map();
|
|
114
|
+
const claimed = new Set();
|
|
115
|
+
for (const c of candidates) {
|
|
116
|
+
if (claimed.has(c.trackId) || assignment.has(c.detIndex))
|
|
117
|
+
continue;
|
|
118
|
+
assignment.set(c.detIndex, c.trackId);
|
|
119
|
+
claimed.add(c.trackId);
|
|
120
|
+
}
|
|
121
|
+
const out = [];
|
|
122
|
+
detections.forEach((det, detIndex) => {
|
|
123
|
+
const matchedId = assignment.get(detIndex);
|
|
124
|
+
const id = matchedId ?? this.nextId++;
|
|
125
|
+
const firstSeen = matchedId !== undefined ? this.tracks.get(matchedId).firstSeen : now;
|
|
126
|
+
const record = {
|
|
127
|
+
id,
|
|
128
|
+
box: { x: det.x, y: det.y, width: det.width, height: det.height },
|
|
129
|
+
firstSeen,
|
|
130
|
+
lastSeen: now,
|
|
131
|
+
};
|
|
132
|
+
this.tracks.set(id, record);
|
|
133
|
+
out.push(record);
|
|
134
|
+
});
|
|
135
|
+
this.enforceCap(claimed);
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
/** Live tracks, for callers that need to inspect state. */
|
|
139
|
+
active() {
|
|
140
|
+
return [...this.tracks.values()];
|
|
141
|
+
}
|
|
142
|
+
reset() {
|
|
143
|
+
this.tracks.clear();
|
|
144
|
+
this.nextId = 1;
|
|
145
|
+
}
|
|
146
|
+
pruneStale(now) {
|
|
147
|
+
for (const [id, track] of this.tracks) {
|
|
148
|
+
if (now - track.lastSeen > this.staleMs)
|
|
149
|
+
this.tracks.delete(id);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
enforceCap(claimedThisFrame) {
|
|
153
|
+
if (this.tracks.size <= this.maxTracks)
|
|
154
|
+
return;
|
|
155
|
+
// Stalest first, and never a track seen in THIS frame — evicting one of
|
|
156
|
+
// those would hand a present person a brand-new id on the next frame.
|
|
157
|
+
const evictable = [...this.tracks.values()]
|
|
158
|
+
.filter((t) => !claimedThisFrame.has(t.id))
|
|
159
|
+
.sort((a, b) => a.lastSeen - b.lastSeen);
|
|
160
|
+
let over = this.tracks.size - this.maxTracks;
|
|
161
|
+
for (const track of evictable) {
|
|
162
|
+
if (over <= 0)
|
|
163
|
+
break;
|
|
164
|
+
this.tracks.delete(track.id);
|
|
165
|
+
over -= 1;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
exports.CentroidTracker = CentroidTracker;
|
|
170
|
+
//# sourceMappingURL=centroidTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"centroidTracker.js","sourceRoot":"","sources":["../src/centroidTracker.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -24,4 +24,6 @@ export { ModelManager } from './ModelManager';
|
|
|
24
24
|
export type { ModelManagerOptions, ModelInfo, ModelVersionResponse } from './ModelManager';
|
|
25
25
|
export { ZKAudienceProver } from './ZKAudienceProver';
|
|
26
26
|
export type { AudienceObservation, AudienceAggregate, AudienceProof, VerificationResult, } from './ZKAudienceProver';
|
|
27
|
+
export { CentroidTracker, DEFAULT_MATCH_RATIO, DEFAULT_STALE_MS, DEFAULT_MAX_TRACKS, } from './centroidTracker';
|
|
28
|
+
export type { TrackedBox, TrackRecord, CentroidTrackerOptions } from './centroidTracker';
|
|
27
29
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EACV,+BAA+B,EAC/B,oBAAoB,EACpB,cAAc,EACd,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,YAAY,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,YAAY,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,YAAY,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACtE,OAAO,EACL,yBAAyB,EACzB,KAAK,mBAAmB,GACzB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,aAAa,EACb,YAAY,EACZ,kBAAkB,GACnB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AACtE,YAAY,EACV,+BAA+B,EAC/B,oBAAoB,EACpB,cAAc,EACd,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,mBAAmB,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAC3F,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,YAAY,EACV,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,kBAAkB,GACnB,MAAM,oBAAoB,CAAC;AAK5B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -15,7 +15,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
16
16
|
};
|
|
17
17
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
-
exports.ZKAudienceProver = exports.ModelManager = exports.MemoryTier = exports.MemoryAttenuationManager = exports.getAttenuationTier = exports.getShedOrder = exports.isModelActive = exports.getCapabilityMatrix = exports.computeTier = exports.classifyObservationSignal = exports.StatusServer = exports.TelemetryScheduler = exports.RecoveryLadder = exports.SubsystemHealthRegistry = exports.SqliteStore = exports.JsonFileStore = exports.SignalBuffer = exports.VASWeightConfig = exports.SocketManager = exports.SensingConfig = exports.DeviceIdentity = void 0;
|
|
18
|
+
exports.DEFAULT_MAX_TRACKS = exports.DEFAULT_STALE_MS = exports.DEFAULT_MATCH_RATIO = exports.CentroidTracker = exports.ZKAudienceProver = exports.ModelManager = exports.MemoryTier = exports.MemoryAttenuationManager = exports.getAttenuationTier = exports.getShedOrder = exports.isModelActive = exports.getCapabilityMatrix = exports.computeTier = exports.classifyObservationSignal = exports.StatusServer = exports.TelemetryScheduler = exports.RecoveryLadder = exports.SubsystemHealthRegistry = exports.SqliteStore = exports.JsonFileStore = exports.SignalBuffer = exports.VASWeightConfig = exports.SocketManager = exports.SensingConfig = exports.DeviceIdentity = void 0;
|
|
19
19
|
__exportStar(require("./types"), exports);
|
|
20
20
|
var DeviceIdentity_1 = require("./DeviceIdentity");
|
|
21
21
|
Object.defineProperty(exports, "DeviceIdentity", { enumerable: true, get: function () { return DeviceIdentity_1.DeviceIdentity; } });
|
|
@@ -55,4 +55,12 @@ var ModelManager_1 = require("./ModelManager");
|
|
|
55
55
|
Object.defineProperty(exports, "ModelManager", { enumerable: true, get: function () { return ModelManager_1.ModelManager; } });
|
|
56
56
|
var ZKAudienceProver_1 = require("./ZKAudienceProver");
|
|
57
57
|
Object.defineProperty(exports, "ZKAudienceProver", { enumerable: true, get: function () { return ZKAudienceProver_1.ZKAudienceProver; } });
|
|
58
|
+
// ONE nearest-centroid tracker. Three independent implementations existed and
|
|
59
|
+
// disagreed; this is the TypeScript half consolidated onto the only correct one.
|
|
60
|
+
// Read its header before writing a fourth.
|
|
61
|
+
var centroidTracker_1 = require("./centroidTracker");
|
|
62
|
+
Object.defineProperty(exports, "CentroidTracker", { enumerable: true, get: function () { return centroidTracker_1.CentroidTracker; } });
|
|
63
|
+
Object.defineProperty(exports, "DEFAULT_MATCH_RATIO", { enumerable: true, get: function () { return centroidTracker_1.DEFAULT_MATCH_RATIO; } });
|
|
64
|
+
Object.defineProperty(exports, "DEFAULT_STALE_MS", { enumerable: true, get: function () { return centroidTracker_1.DEFAULT_STALE_MS; } });
|
|
65
|
+
Object.defineProperty(exports, "DEFAULT_MAX_TRACKS", { enumerable: true, get: function () { return centroidTracker_1.DEFAULT_MAX_TRACKS; } });
|
|
58
66
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;;;;;;;;;;;;;AAEtF,0CAAwB;AACxB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AAEvB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAE3B,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,6EAGuC;AAFrC,wIAAA,yBAAyB,OAAA;AAG3B,iDAMyB;AALvB,4GAAA,WAAW,OAAA;AACX,oHAAA,mBAAmB,OAAA;AACnB,8GAAA,aAAa,OAAA;AACb,6GAAA,YAAY,OAAA;AACZ,mHAAA,kBAAkB,OAAA;AAEpB,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AAOjC,uEAAwD;AAA/C,sHAAA,UAAU,OAAA;AACnB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,sFAAsF;;;;;;;;;;;;;;;;;AAEtF,0CAAwB;AACxB,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AACvB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AAEtB,qDAAoD;AAA3C,kHAAA,eAAe,OAAA;AACxB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,iDAAgD;AAAvC,8GAAA,aAAa,OAAA;AACtB,6CAA4C;AAAnC,0GAAA,WAAW,OAAA;AACpB,qEAAoE;AAA3D,kIAAA,uBAAuB,OAAA;AAChC,mDAAkD;AAAzC,gHAAA,cAAc,OAAA;AAEvB,2DAA0D;AAAjD,wHAAA,kBAAkB,OAAA;AAE3B,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,6EAGuC;AAFrC,wIAAA,yBAAyB,OAAA;AAG3B,iDAMyB;AALvB,4GAAA,WAAW,OAAA;AACX,oHAAA,mBAAmB,OAAA;AACnB,8GAAA,aAAa,OAAA;AACb,6GAAA,YAAY,OAAA;AACZ,mHAAA,kBAAkB,OAAA;AAEpB,uEAAsE;AAA7D,oIAAA,wBAAwB,OAAA;AAOjC,uEAAwD;AAA/C,sHAAA,UAAU,OAAA;AACnB,+CAA8C;AAArC,4GAAA,YAAY,OAAA;AAErB,uDAAsD;AAA7C,oHAAA,gBAAgB,OAAA;AAQzB,8EAA8E;AAC9E,iFAAiF;AACjF,2CAA2C;AAC3C,qDAK2B;AAJzB,kHAAA,eAAe,OAAA;AACf,sHAAA,mBAAmB,OAAA;AACnB,mHAAA,gBAAgB,OAAA;AAChB,qHAAA,kBAAkB,OAAA"}
|
package/package.json
CHANGED