import assert from 'node:assert/strict'; import { createHash } from 'node:crypto'; import { readFileSync } from 'node:fs'; import { Worker } from 'node:worker_threads'; import { performance } from 'node:perf_hooks'; import { generateMap } from './mapPipeline.js'; import { createWorldMap } from './worldMap.js'; import { MAP_H } from './mapUtils.js'; import { collectTransferableBuffers } from './transferUtils.js'; function hashView(view) { return createHash('sha256').update(Buffer.from(view.buffer, view.byteOffset, view.byteLength)).digest('hex'); } function derivePatchSeed(baseSeed, rect, terrainType, variant = 0) { let h = (baseSeed >>> 0) ^ 0x9e3779b9; h = Math.imul(h ^ (rect.x0 | 0), 1664525) >>> 0; h = Math.imul(h ^ (rect.y0 | 0), 1013904223) >>> 0; h = Math.imul(h ^ (rect.x1 | 0), 2246822519) >>> 0; h = Math.imul(h ^ (rect.y1 | 0), 3266489917) >>> 0; h = Math.imul(h ^ (variant >>> 0), 668265263) >>> 0; for (const ch of String(terrainType || 'auto')) h = Math.imul(h ^ ch.charCodeAt(0), 16777619) >>> 0; return h >>> 0; } function browserWorkerAdapter(moduleUrl) { const target = moduleUrl.href; const code = ` import { parentPort } from 'node:worker_threads'; globalThis.self = { onmessage: null, postMessage(message, transfer) { parentPort.postMessage(message, transfer); } }; await import(${JSON.stringify(target)}); parentPort.on('message', (data) => self.onmessage?.({ data })); `; return new Worker(new URL(`data:text/javascript,${encodeURIComponent(code)}`), { type: 'module', execArgv: [] }); } async function runPatchWorker(baseWorld, rect, baseSeed, variant) { const worker = browserWorkerAdapter(new URL('./mapPatchWorker.js', import.meta.url)); const preview = structuredClone(baseWorld); const transfer = Array.from(collectTransferableBuffers(preview)); const started = performance.now(); const message = await new Promise((resolve, reject) => { worker.on('message', (m) => { if (m?.type !== 'progress') resolve(m); }); worker.on('error', reject); worker.postMessage({ id: variant + 1, world: preview, rect, options: { patchMode: 'expansion', terrainType: 'auto', seed: derivePatchSeed(baseSeed, rect, 'auto', variant), variant, maxQualityRetries: 0, qualityTerrainAttempts: 1, }, }, transfer); }); await worker.terminate(); assert.equal(message.ok, true, `variant ${variant} worker failed: ${message.error || 'unknown'}`); assert.equal(message.result?.ok, true, `variant ${variant} patch failed: ${message.result?.code || message.result?.reason || 'unknown'}`); return { message, seconds: (performance.now() - started) / 1000 }; } const appSource = readFileSync(new URL('./app.js', import.meta.url), 'utf8'); const viewportSource = readFileSync(new URL('./worldViewport.js', import.meta.url), 'utf8'); const rendererSource = readFileSync(new URL('./renderer.js', import.meta.url), 'utf8'); assert.match(appSource, /maxQualityRetries:\s*0/); assert.match(appSource, /patchBusy/); assert.match(appSource, /previewPatchDelta/); assert.match(appSource, /renderRevision/); assert.match(appSource, /worker\.terminate\?\.\(\)/); assert.match(viewportSource, /viewport\.renderRevision/); assert.match(rendererSource, /map\?\.renderRevision/); const baseSeed = 1; const baseWorld = createWorldMap(generateMap(baseSeed, { terrainType: 'auto', onProgress() {} })); const ox = baseWorld.originX; const oy = baseWorld.originY; const rect = { kind: 'lasso', polygon: [ { x: ox - 145, y: oy - 14 }, { x: ox + 8, y: oy - 14 }, { x: ox + 8, y: oy + MAP_H + 14 }, { x: ox - 145, y: oy + MAP_H + 14 }, ] }; rect.x0 = ox - 145; rect.y0 = oy - 14; rect.x1 = ox + 8; rect.y1 = oy + MAP_H + 14; const a = await runPatchWorker(baseWorld, rect, baseSeed, 0); const b = await runPatchWorker(baseWorld, rect, baseSeed, 1); const aWorld = a.message.world; const bWorld = b.message.world; const hashesA = { elevation: hashView(aWorld.fields.elevation), sea: hashView(aWorld.fields.sea), admin: hashView(aWorld.fields.adminId), }; const hashesB = { elevation: hashView(bWorld.fields.elevation), sea: hashView(bWorld.fields.sea), admin: hashView(bWorld.fields.adminId), }; assert.notEqual(hashesA.elevation, hashesB.elevation, 'Alternative variants generated identical elevation'); assert.notEqual(hashesA.sea, hashesB.sea, 'Alternative variants generated identical sea mask'); assert.notEqual(hashesA.admin, hashesB.admin, 'Alternative variants generated identical administration'); assert.equal(a.message.result.qualityRetryCount || 0, 0); assert.equal(b.message.result.qualityRetryCount || 0, 0); assert.equal(a.message.result.candidateQuality?.selectedVariant, 0, 'variant 0 did not render its exact requested terrain variant'); assert.equal(b.message.result.candidateQuality?.selectedVariant, 1, 'variant 1 did not render its exact requested terrain variant'); assert.equal(a.message.result.seamDiagnostics?.status, 'clean'); assert.equal(b.message.result.seamDiagnostics?.status, 'clean'); console.log(JSON.stringify({ ok: true, interactiveRetryPolicy: 'one requested variant per click; no hidden whole-patch retry', variants: [ { variant: 0, seconds: Math.round(a.seconds * 100) / 100, selectedVariant: a.message.result.candidateQuality?.selectedVariant, hashes: hashesA }, { variant: 1, seconds: Math.round(b.seconds * 100) / 100, selectedVariant: b.message.result.candidateQuality?.selectedVariant, hashes: hashesB }, ], alternativesDiffer: true, explicitRenderRevision: true, singlePatchWorkerLifetime: true, }, null, 2));