Keep traffic vehicles and road flow across globe switches

This commit is contained in:
German Khokhlov committed 2026-11-03 04:09:21 +04:00
1 parent 4e09559337
commit 75df3389f3
20 files changed
+586 -109

No files matched your search

+1
View File
@@ -3679,6 +3679,7 @@
"src/layers/shared/render/navaraStems.js",
"src/layers/submarineCables/render/navara.js",
"src/layers/directions/render/navara.js",
"src/layers/traffic/render/navara.js",
"src/layers/shared/render/navaraStory.js",
"src/layers/bhoteKoshi/render/navara.js",
"src/layers/weather/render/navara.js",
+182
View File
@@ -0,0 +1,182 @@
import { trafficFixtureResponse } from './traffic-fixtures.mjs';
import puppeteer from 'puppeteer';
import sharp from 'sharp';
import assert from 'node:assert/strict';
import { blockPaidQaMaps } from './qa-map-policy.mjs';
const base = new URL(process.argv[2]);
if (
!['localhost', '127.0.0.1'].includes(base.hostname) ||
['', '4173', '4185', '4186', '4187', '4188', '4189', '4194'].includes(
base.port,
)
)
throw new Error('Supply an unreserved local keyless preview URL');
base.search = '?engine=navara&welcome=0&look=cinematic';
base.hash =
'v=2&lat=30.2670&lon=-97.7440&alt=1800&heading=0&pitch=-90&roll=0&map=sentinel2&l=';
const b = await puppeteer.launch({
headless: true,
args: ['--use-angle=metal', '--enable-gpu'],
});
try {
const p = await b.newPage();
await blockPaidQaMaps(p);
await p.setViewport({ width: 1024, height: 768 });
const errors = [];
p.on('pageerror', (e) => {
errors.push(e.message);
console.log('error', e.message.split('?')[0]);
});
const keyless = process.argv.includes('--simulation');
const reads = new Map();
await p.setRequestInterception(true);
p.on('request', async (req) => {
const u = new URL(req.url());
if (
u.hostname === 'tiles.openfreemap.org' ||
u.pathname.startsWith('/api/tomtom/')
) {
reads.set(u.href, (reads.get(u.href) || 0) + 1);
if (keyless && u.pathname === '/api/tomtom/status')
return req.respond({
status: 200,
contentType: 'application/json',
body: '{"hasKey":false}',
});
const response = trafficFixtureResponse(req);
if (response) return req.respond(response);
throw Error('unrecognized traffic URL: ' + u.pathname);
}
return req.continue();
});
p.on('console', (msg) => {
if (msg.type() === 'error' && /Shader|WebGLProgram/i.test(msg.text()))
errors.push(msg.text());
});
await p.goto(base.href);
const ready = async (kind) => {
await p.waitForFunction(
(k) =>
window.__godsEyeView?.engine.kind === k &&
!document.querySelector('#globe-engine')?.disabled &&
!document.querySelector('.engine-switch-frame') &&
document.querySelector('#loading-screen.hidden'),
{ timeout: 90000 },
kind,
);
await p.evaluate(
() => window.__godsEyeView.styleManager.initialRestorePromise,
);
};
await ready('navara');
await p.evaluate(async () => {
const { tileset, dataManager } = window.__godsEyeView;
if (tileset || window.__GOOGLE_MAPS_API_KEY__)
throw Error('Keyless preview required');
window.qaTraffic = dataManager.layers.get('traffic').module;
window.qaTraffic.setParams({ jamViz: 'both' });
await dataManager.setEnabled('traffic', true, { origin: 'user' });
});
const waitTraffic = async () => {
try {
await p.waitForFunction(() => window.qaTraffic.getStats().count >= 10, {
timeout: 40000,
});
} catch (e) {
console.log(
'no traffic',
await p.evaluate(() => window.qaTraffic.getStats()),
);
throw e;
}
};
await waitTraffic();
await new Promise((resolve) => setTimeout(resolve, 2000));
const ids = await p.evaluate(() =>
window.qaTraffic.getDetectableObjects().map((p) => p.id),
);
const first = await p.evaluate(
() => window.qaTraffic.getStats().motion.rebuilds,
);
for (const kind of ['navara', 'cesium', 'navara']) {
if ((await p.evaluate(() => window.__godsEyeView.engine.kind)) !== kind) {
await p.select('#globe-engine', kind);
await ready(kind);
}
await waitTraffic();
const check = await p.evaluate(() => {
const { dataManager } = window.__godsEyeView;
const mod = dataManager.layers.get('traffic').module;
return {
same: mod === window.qaTraffic,
...mod.getStats(),
params: mod.getParams(),
ids: mod.getDetectableObjects().map((p) => p.id),
};
});
console.log(
kind,
check.mode,
check.count,
check.flowBuckets,
check.heatLines,
check.motion,
);
assert.equal(check.same, true);
assert.equal(check.params.jamViz, 'both');
assert.equal(check.error, null);
assert.equal(
check.motion.rebuilds,
first,
'traffic population was cleared',
);
assert.ok(
check.ids.some((id) => ids.includes(id)),
'original moving vehicles survived',
);
if (!keyless)
assert.ok(check.heatLines > 0, 'congestion corridors are published');
if (keyless) assert.equal(check.flowBuckets.sim, check.count);
else assert.ok(check.flowBuckets.slow + check.flowBuckets.jam > 0);
}
if (keyless)
assert.ok(![...reads.keys()].some((u) => u.includes('/tomtom/flow/')));
const pixels = async () =>
sharp(await p.screenshot())
.extract({ left: 360, top: 255, width: 330, height: 260 })
.removeAlpha()
.raw()
.toBuffer();
// Source counts can be ready before the incoming renderer has drawn terrain.
// Let the camera and the newly attached road heights settle before comparison.
await new Promise((resolve) => setTimeout(resolve, 2200));
const shown = await pixels();
await p.evaluate(() =>
window.__godsEyeView.dataManager.setEnabled('traffic', false, {
origin: 'user',
}),
);
await new Promise((resolve) => setTimeout(resolve, 600));
const hidden = await pixels();
let visible = 0;
for (let i = 0; i < shown.length; i += 3) {
if (
shown[i] +
shown[i + 1] +
shown[i + 2] -
(hidden[i] + hidden[i + 1] + hidden[i + 2]) >
110
)
visible++;
}
console.log('changed traffic pixels', visible);
assert.ok(visible > 15, 'changing the layer changes the rendered streets');
assert.deepEqual(errors, []);
console.log(
'PASS retained traffic population and flow, real geography and stable identities across both globes',
);
} finally {
await b.close();
}