import fs from 'fs'; import zlib from 'zlib'; const [mapP, layP] = process.argv.slice(2); const M = JSON.parse(fs.readFileSync(mapP)); const L = JSON.parse(fs.readFileSync(layP)); const fc0 = zlib.gunzipSync(Buffer.from(M.free_class,'base64')); const {nx,ny,res} = M; function down(fc,nx,ny,f){ const X=Math.floor(nx/f),Y=Math.floor(ny/f),o=new Uint8Array(X*Y); for(let y=0;y{const x=i%X,y=(i/X)|0,dx=Math.abs(x-g%X),dy=Math.abs(y-((g/X)|0));return (Math.max(dx,dy)+(Math.SQRT2-1)*Math.min(dx,dy))*r;}; const heap=[],push=(f,i)=>{heap.push([f,i]);let k=heap.length-1;while(k>0){const p=(k-1)>>1;if(heap[p][0]<=heap[k][0])break;[heap[p],heap[k]]=[heap[k],heap[p]];k=p;}}; const pop=()=>{const t=heap[0],l=heap.pop();if(heap.length){heap[0]=l;let k=0;for(;;){let a=2*k+1,b=a+1,m=k;if(a=X||b>=Y)continue;const j=b*X+a;const v=fc[j];if(!v)continue; if(dx&&dy&&(!fc[y*X+a]||!fc[b*X+x]))continue;const w=v===2?1:3;const ng=G[i]+c*r*w;if(ng=0){const p=P[k];len+=Math.hypot(k%X-p%X,((k/X)|0)-((p/X)|0))*r;k=p;}return {len,exp};} const snap=(fc,X,Y,r,[px,py])=>{let best=-1,bd=1e9;const cx=Math.floor(px/r),cy=Math.floor(py/r);for(let d=0;d<40&&best<0;d++)for(let j=-d;j<=d;j++)for(let i=-d;i<=d;i++){const a=cx+i,b=cy+j;if(a<0||b<0||a>=X||b>=Y)continue;if(fc[b*X+a]){const dd=i*i+j*j;if(ddp.kind==='FoodPass').point; for(const f of [1,2,4]){ const [fc,X,Y]=f===1?[fc0,nx,ny]:down(fc0,nx,ny,f);const r=res*f;let t0=performance.now(),rows=[],fail=0; for(const t of L.tables){if(!t.stop)continue;const s=snap(fc,X,Y,r,pass),g=snap(fc,X,Y,r,t.stop);const o=astar(fc,X,Y,r,s,g);const ref=L.routes.from_pass?.[t.id]?.grid_length;if(isNaN(o.len))fail++;rows.push([t.id,o.len,ref,o.exp]);} const ms=performance.now()-t0;const diffs=rows.filter(r=>r[2]&&!isNaN(r[1])).map(r=>Math.abs(r[1]-r[2])); console.log(`cell ${(r*100).toFixed(1)}cm grid ${X}x${Y}: ${rows.length} routes, fail ${fail}, ${(ms/rows.length).toFixed(1)} ms/route, |len-site| mean ${(diffs.reduce((a,b)=>a+b,0)/diffs.length).toFixed(2)} m max ${Math.max(...diffs).toFixed(2)} m`); }