test(08-02): bot-suite encodeGraph call sites carry landmark blocks (full battery green)
webhook corridor/sparse builders + guidance-cron unnamed way compute tiny tables through the ONE preprocessing core (@araharah/routing farthestPointAnchors + landmarkTables) and pass the landmarks block into the same single encodeGraph call — call-site updates, not a second encode function. Graphs with no degree>=2 candidate (sparse, 2-node) pin their anchor explicitly; tables still come from the integer-Dijkstra core. FULL BATTERY at this commit: routing:test 74/74, bot 126/126, both typechecks clean; the regenerated fixture is deterministic (byte- identical re-run); mini-graph-arg1.bin is byte-stable vs its committed 08-01 bytes.
This commit is contained in:
@@ -49,6 +49,7 @@ const { strings } = await import("../src/i18n/strings.ts");
|
|||||||
const { encodePolyline6 } = await import("@araharah/routing/src/polyline.ts");
|
const { encodePolyline6 } = await import("@araharah/routing/src/polyline.ts");
|
||||||
const { deriveCumulativeDistanceM, haversineM } = await import("@araharah/routing/src/geo.ts");
|
const { deriveCumulativeDistanceM, haversineM } = await import("@araharah/routing/src/geo.ts");
|
||||||
const { encodeGraph, decodeGraph } = await import("@araharah/routing/src/graph.ts");
|
const { encodeGraph, decodeGraph } = await import("@araharah/routing/src/graph.ts");
|
||||||
|
const { LANDMARK_QUANTUM_S, landmarkTables } = await import("@araharah/routing/src/landmark.ts");
|
||||||
|
|
||||||
/* ————— geometry helpers (1e-6-grid-exact construction, the codec's grid law) ————— */
|
/* ————— geometry helpers (1e-6-grid-exact construction, the codec's grid law) ————— */
|
||||||
|
|
||||||
@@ -249,15 +250,23 @@ test("GC6b unnamed matched edge → cardStreetUnnamed ('UNNAMED ROAD') — still
|
|||||||
// A purpose-built unnamed way through the same encodeGraph contract
|
// A purpose-built unnamed way through the same encodeGraph contract
|
||||||
// (names: [] → every edge carries the UNNAMED_NAME_ID sentinel).
|
// (names: [] → every edge carries the UNNAMED_NAME_ID sentinel).
|
||||||
const meters = haversineM({ lat: 3.15, lng: 101.69 }, { lat: 3.1505, lng: 101.69 });
|
const meters = haversineM({ lat: 3.15, lng: 101.69 }, { lat: 3.1505, lng: 101.69 });
|
||||||
|
const edges = [
|
||||||
|
{ from: 0, to: 1, seconds: meters / (30 / 3.6) },
|
||||||
|
{ from: 1, to: 0, seconds: meters / (30 / 3.6) },
|
||||||
|
];
|
||||||
|
// A 2-node graph has no degree>=2 farthest-point candidate (the selection
|
||||||
|
// filter), so the anchor pins directly — the tables still come from the
|
||||||
|
// ONE integer-Dijkstra core (08-02), through the ONE encode authority.
|
||||||
|
const landmarkInput = { nodeCount: 2, edges, quantumS: LANDMARK_QUANTUM_S };
|
||||||
|
const anchors = Uint32Array.of(0);
|
||||||
|
const { to, from } = landmarkTables(landmarkInput, anchors);
|
||||||
const buf = encodeGraph({
|
const buf = encodeGraph({
|
||||||
lat: [3.15, 3.1505],
|
lat: [3.15, 3.1505],
|
||||||
lng: [101.69, 101.69],
|
lng: [101.69, 101.69],
|
||||||
edges: [
|
edges,
|
||||||
{ from: 0, to: 1, seconds: meters / (30 / 3.6) },
|
|
||||||
{ from: 1, to: 0, seconds: meters / (30 / 3.6) },
|
|
||||||
],
|
|
||||||
names: [],
|
names: [],
|
||||||
maxSpeedKmh: 30,
|
maxSpeedKmh: 30,
|
||||||
|
landmarks: { quantumS: LANDMARK_QUANTUM_S, nodes: anchors, to, from },
|
||||||
});
|
});
|
||||||
const graph = decodeGraph(buf);
|
const graph = decodeGraph(buf);
|
||||||
assert.notEqual(graph, null);
|
assert.notEqual(graph, null);
|
||||||
|
|||||||
@@ -472,6 +472,22 @@ test("GW11 PUT /api/guidance → 405", async () => {
|
|||||||
|
|
||||||
const { encodeGraph } = await import("../../routing/src/graph.ts");
|
const { encodeGraph } = await import("../../routing/src/graph.ts");
|
||||||
const { haversineM } = await import("../../routing/src/geo.ts");
|
const { haversineM } = await import("../../routing/src/geo.ts");
|
||||||
|
const { LANDMARK_QUANTUM_S, farthestPointAnchors, landmarkTables } = await import(
|
||||||
|
"../../routing/src/landmark.ts"
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Tiny REAL landmark block through the ONE preprocessing core (08-02):
|
||||||
|
* farthest-point anchor + integer ĉ tables — computed, never faked.
|
||||||
|
* `{ pin }` pins the anchor for graphs with no degree>=2 candidate (the
|
||||||
|
* selection filter's law — e.g. a single-segment graph); the tables still
|
||||||
|
* come from the ONE integer-Dijkstra core. */
|
||||||
|
function landmarkBlock(nodeCount, edges, { pin } = {}) {
|
||||||
|
const input = { nodeCount, edges, quantumS: LANDMARK_QUANTUM_S };
|
||||||
|
const anchors = pin !== undefined ? Uint32Array.of(pin) : farthestPointAnchors(input, 1);
|
||||||
|
if (anchors.length !== 1) throw new Error("graph has no degree-2 anchor candidate");
|
||||||
|
const { to, from } = landmarkTables(input, anchors);
|
||||||
|
return { quantumS: LANDMARK_QUANTUM_S, nodes: anchors, to, from };
|
||||||
|
}
|
||||||
|
|
||||||
/** The committed 06-01 ground truth (25 nodes around KL center) via fs. */
|
/** The committed 06-01 ground truth (25 nodes around KL center) via fs. */
|
||||||
const MINI_GRAPH = readFileSync(new URL("../../routing/test/fixtures/mini-graph.bin", import.meta.url));
|
const MINI_GRAPH = readFileSync(new URL("../../routing/test/fixtures/mini-graph.bin", import.meta.url));
|
||||||
@@ -496,7 +512,14 @@ function corridorGraphBuffer({ gap = false } = {}) {
|
|||||||
const seconds = meters / (60 / 3.6);
|
const seconds = meters / (60 / 3.6);
|
||||||
edges.push({ from: i, to: i + 1, seconds, nameId: 0 }, { from: i + 1, to: i, seconds, nameId: 0 });
|
edges.push({ from: i, to: i + 1, seconds, nameId: 0 }, { from: i + 1, to: i, seconds, nameId: 0 });
|
||||||
}
|
}
|
||||||
return encodeGraph({ lat, lng, edges, names: ["Jalan Koridor Ujian"], maxSpeedKmh: 60 });
|
return encodeGraph({
|
||||||
|
lat,
|
||||||
|
lng,
|
||||||
|
edges,
|
||||||
|
names: ["Jalan Koridor Ujian"],
|
||||||
|
maxSpeedKmh: 60,
|
||||||
|
landmarks: { ...landmarkBlock(n, edges) },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Nodes cluster at two far-apart cells with a nodeless middle: an in-bbox
|
/** Nodes cluster at two far-apart cells with a nodeless middle: an in-bbox
|
||||||
@@ -506,15 +529,17 @@ function sparseGraphBuffer() {
|
|||||||
const lng = [101.69, 101.6905, 101.7];
|
const lng = [101.69, 101.6905, 101.7];
|
||||||
const meters = haversineM({ lat: lat[0], lng: lng[0] }, { lat: lat[1], lng: lng[1] });
|
const meters = haversineM({ lat: lat[0], lng: lng[0] }, { lat: lat[1], lng: lng[1] });
|
||||||
const seconds = meters / (50 / 3.6);
|
const seconds = meters / (50 / 3.6);
|
||||||
|
const edges = [
|
||||||
|
{ from: 0, to: 1, seconds, nameId: 0 },
|
||||||
|
{ from: 1, to: 0, seconds, nameId: 0 },
|
||||||
|
];
|
||||||
return encodeGraph({
|
return encodeGraph({
|
||||||
lat,
|
lat,
|
||||||
lng,
|
lng,
|
||||||
edges: [
|
edges,
|
||||||
{ from: 0, to: 1, seconds, nameId: 0 },
|
|
||||||
{ from: 1, to: 0, seconds, nameId: 0 },
|
|
||||||
],
|
|
||||||
names: ["Jalan Sparse Ujian"],
|
names: ["Jalan Sparse Ujian"],
|
||||||
maxSpeedKmh: 50,
|
maxSpeedKmh: 50,
|
||||||
|
landmarks: { ...landmarkBlock(lat.length, edges, { pin: 0 }) },
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user