mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
Knip, configured with the application, package exports, scripts, QA harnesses, workers, tools and tests as entry points, reports exports that no module imports. Each was checked by hand against string-based and namespace imports. - Symbols that are still used inside their own module lose only the `export` keyword (176 constants and helpers). - Unused re-exports are removed from barrel modules (flight, military, vessel, CCTV, directions, transit history, local ADS-B and street-level policy modules). - Declarations that nothing uses at all are deleted, among them AIS_WATCHDOG_STATUSES, applyFilter, isRadioCountryCode, compactText, DENSITY_STOPS, the unused CCTV endpoint constants, and the SDR band constants. - Default exports that nothing imports are removed. The ones in src/data/earthquakes.js, src/data/telegeographySubmarineCables.js, src/data/wind.js and src/data/bhoteKoshiLocator.js each constructed a layer instance at import time that nothing used; those instances are no longer created. Every export of a package.json entry stays, as does TOMTOM_CREDIT, which the traffic layer reads from the credits namespace it is given.
126 lines
3.6 KiB
JavaScript
126 lines
3.6 KiB
JavaScript
const DEFAULT_MAX_COHORT = 256;
|
|
|
|
/** Resolve the review-mandated bounded materialization cap for a layer quota. */
|
|
export function cohortCapForQuota(quota) {
|
|
const normalized = Math.max(0, Math.floor(Number(quota) || 0));
|
|
return Math.min(DEFAULT_MAX_COHORT, Math.max(64, normalized * 4));
|
|
}
|
|
|
|
/** Stable FNV-1a identity hash used only on solve ticks. */
|
|
export function stableIdentityHash(layerId, sourceId) {
|
|
const text = `${String(layerId)}\u0000${String(sourceId)}`;
|
|
let hash = 2166136261;
|
|
for (let i = 0; i < text.length; i++) {
|
|
hash ^= text.charCodeAt(i);
|
|
hash = Math.imul(hash, 16777619);
|
|
}
|
|
return hash >>> 0;
|
|
}
|
|
|
|
/** Negative means a is a better deterministic contender than b. */
|
|
function compareCohortContenders(a, b) {
|
|
const priorityDelta =
|
|
(Number(b?._cohortPriority) || 0) - (Number(a?._cohortPriority) || 0);
|
|
if (priorityDelta) return priorityDelta;
|
|
const bandDelta =
|
|
(Number(b?._cohortBand) || 0) - (Number(a?._cohortBand) || 0);
|
|
if (bandDelta) return bandDelta;
|
|
const hashDelta =
|
|
(Number(a?._cohortHash) >>> 0) - (Number(b?._cohortHash) >>> 0);
|
|
if (hashDelta) return hashDelta;
|
|
return String(a?._cohortSourceId).localeCompare(String(b?._cohortSourceId));
|
|
}
|
|
|
|
function isWorse(a, b) {
|
|
return compareCohortContenders(a, b) > 0;
|
|
}
|
|
|
|
/**
|
|
* Streaming deterministic contender reservoir. The heap retains at most 256
|
|
* non-incumbents per layer, so a 12k-object scan never creates or sorts a full
|
|
* rich-candidate population.
|
|
*/
|
|
export class BoundedCohort {
|
|
constructor(maxSize = DEFAULT_MAX_COHORT, hardMax = DEFAULT_MAX_COHORT) {
|
|
const ceiling = Math.max(
|
|
1,
|
|
Math.floor(Number(hardMax) || DEFAULT_MAX_COHORT),
|
|
);
|
|
this.maxSize = Math.max(
|
|
1,
|
|
Math.min(ceiling, Math.floor(Number(maxSize) || DEFAULT_MAX_COHORT)),
|
|
);
|
|
this.incumbents = [];
|
|
this.heap = [];
|
|
}
|
|
|
|
consider(observation, incumbent = false) {
|
|
if (!observation) return;
|
|
if (incumbent) {
|
|
this.incumbents.push(observation);
|
|
return;
|
|
}
|
|
if (this.heap.length < this.maxSize) {
|
|
this.heap.push(observation);
|
|
this._bubbleUp(this.heap.length - 1);
|
|
return;
|
|
}
|
|
if (compareCohortContenders(observation, this.heap[0]) >= 0) return;
|
|
this.heap[0] = observation;
|
|
this._siftDown(0);
|
|
}
|
|
|
|
values(limit = this.maxSize) {
|
|
const cap = Math.max(
|
|
0,
|
|
Math.min(this.maxSize, Math.floor(Number(limit) || 0)),
|
|
);
|
|
const incumbents = this.incumbents
|
|
.slice()
|
|
.sort(compareCohortContenders)
|
|
.slice(0, cap);
|
|
const remaining = Math.max(0, cap - incumbents.length);
|
|
if (remaining === 0) return incumbents;
|
|
const contenders = this.heap
|
|
.slice()
|
|
.sort(compareCohortContenders)
|
|
.slice(0, remaining);
|
|
return incumbents.concat(contenders);
|
|
}
|
|
|
|
_bubbleUp(index) {
|
|
let current = index;
|
|
while (current > 0) {
|
|
const parent = Math.floor((current - 1) / 2);
|
|
if (!isWorse(this.heap[current], this.heap[parent])) break;
|
|
[this.heap[current], this.heap[parent]] = [
|
|
this.heap[parent],
|
|
this.heap[current],
|
|
];
|
|
current = parent;
|
|
}
|
|
}
|
|
|
|
_siftDown(index) {
|
|
let current = index;
|
|
while (true) {
|
|
const left = current * 2 + 1;
|
|
const right = left + 1;
|
|
let worst = current;
|
|
if (left < this.heap.length && isWorse(this.heap[left], this.heap[worst]))
|
|
worst = left;
|
|
if (
|
|
right < this.heap.length &&
|
|
isWorse(this.heap[right], this.heap[worst])
|
|
)
|
|
worst = right;
|
|
if (worst === current) return;
|
|
[this.heap[current], this.heap[worst]] = [
|
|
this.heap[worst],
|
|
this.heap[current],
|
|
];
|
|
current = worst;
|
|
}
|
|
}
|
|
}
|