class Runescape{constructor(){this.mondrian=null,this.txList=[]}launch(t,i){this.blockHeight=`${t}`,this.txValueCache=i,this.loadRoutine()}async loadRoutine(){window.THREE=await import("/content/0d013bb60fc5bf5a6c77da7371b07dc162ebc7d7f3af0ff3bd00ae5f0c546445i0");const{default:t}=await import("/content/036f12ea42d0fd664948e952b61f4c2f0d04e5672e7a7b3e2c33ac2544b6b1a7i0"),{POSTPROCESSING:i}=await import("/content/5f68b5b0e97c51679eba9f8987fc3945dc04fc894a0bb7c099385145cbd3a617i0"),e=i.BloomEffect,o=i.EffectComposer,s=i.EffectPass,n=i.RenderPass,r=i.BlendFunction,a={headers:{Accept:"application/json"}},l=await fetch("/r/blockheight",a),h=await l.json(),p=await fetch(`/r/blockinfo/${h}`,a),d=await p.json();console.log("latest blockHeight",h,"tx_count",d.transaction_count);const c=Math.floor(d.transaction_count/2);console.log("treasure tx: 1/2 tx x latest tx_count =",c),await this.fetchData();const x=c<this.txList.length?this.txList[c].value:0;console.log("treasure tx #",c,"in block",this.blockHeight,"has tx value in total of",x,"sats");for(let t=0;t<this.txList.length;t++)this.txList[t].size=this.logTxSize(this.txList[t].value);let f=0;for(let t of this.txList)f+=t.size*t.size;let w=Math.ceil(Math.sqrt(f));this.mondrian=new MondrianLayout(w,w),t.install({THREE:THREE});const u=window.innerWidth,g=window.innerHeight,m=new THREE.Clock,y=new THREE.Scene,E=new THREE.PerspectiveCamera(90,u/g,.01,1e3);E.position.set(0,w/1.6,0);const M=new THREE.WebGLRenderer({powerPreference:"high-performance",antialias:!1,stencil:!1,depth:!1});M.setSize(u,g),M.shadowMap.enabled=!0,M.shadowMap.type=THREE.BasicShadowMap;let b=new THREE.HemisphereLight(16777215,0,2);y.add(b);let R=new THREE.DirectionalLight(16777215,1);R.position.set(-10,100,-10),R.target.position.set(0,0,0),R.castShadow=!0,y.add(R),document.getElementById("root").appendChild(M.domElement);const S=new t(E,M.domElement);let T=13576336;this.blockHeight<84e4&&(T=16356896);const H=new THREE.MeshStandardMaterial({color:T,wireframe:!1}),L=new THREE.MeshStandardMaterial({color:16775424,wireframe:!1,roughness:.375}),k=new o(M);k.addPass(new n(y,E));const v=new e({blendFunction:r.ADD,mipmapBlur:!0,luminanceThreshold:.4,luminanceSmoothing:.12,intensity:2});k.addPass(new s(E,v));let C=0;for(let t=0;t<this.txList.length;t++){const i=this.mondrian.place(this.txList[t].size),e=.5*i.r,o=new THREE.Mesh(new THREE.BoxGeometry(.9*i.r,.2*i.r,.9*i.r),this.txList[t].value===x?L:H);this.txList[t].value===x&&(C+=1),y.add(o),o.position.set(i.position.x-w/2+e,.1*i.r/2,i.position.y-w/2+e)}console.log("found",C,1!==C?"treasure parcels":"treasure parcel","with the same output value for BlockDrop"),M.render(y,E),k.render();let P=!1;!function t(){const i=m.getDelta(),e=m.getElapsedTime(),o=S.update(i);P&&(v.intensity=2+2*Math.sin(e),k.render(),e>30&&(P=!1)),requestAnimationFrame(t),o&&(P=!0)}()}async fetchData(){const t=await fetch(this.txValueCache).then((t=>t.text()));if(t){let i=t.split(/\r?\n/);this.txList=new Array(i.length);for(let t=0;t<i.length;t++){let e=parseInt(i[t]);this.txList[t]={value:e}}}}decompress=t=>{const i=Uint8Array.from(atob(t),(t=>t.charCodeAt(0))),e=new DecompressionStream("gzip"),o=e.writable.getWriter();return o.write(i),o.close(),new Response(e.readable).arrayBuffer().then((function(t){return(new TextDecoder).decode(t)}))};logTxSize(t){if(0===t)return 1;let i=Math.ceil(Math.log10(t))-5;return Math.min(Number.MAX_SAFE_INTEGER,Math.max(1,i))}}class MondrianLayout{constructor(t,i){this.width=t,this.height=i,this.xMax=0,this.yMax=0,this.rowOffset=0,this.rows=[],this.txMap=[]}getSize(){return{width:this.xMax,height:this.yMax}}getRow(t){let i=t.y-this.rowOffset;return i<this.rows.length?this.rows[i]:null}getSlot(t){let i=this.getRow(t);return null!==i&&i.map.hasOwnProperty(t.x)?i.map[t.x]:null}addRow(){let t={y:this.rows.length+this.rowOffset,slots:[],map:{},max:0};return this.rows.push(t),t}addSlot(t){if(t.r<=0)return null;let i=this.getSlot(t.position);if(null!==i)return i.r=Math.max(i.r,t.r),i;{let i=this.getRow(t.position);if(null===i)return null;let e=i.slots.findIndex((i=>i.position.x>t.position.x));return-1===e?i.slots.push(t):i.slots.splice(e,0,t),i.map[t.position.x]=t,t}}removeSlot(t){let i=this.getRow(t.position);if(null!==i){delete i.map[t.position.x];let e=i.slots.findIndex((i=>i.position.x===t.position.x));-1!==e&&i.slots.splice(e,1)}}fillSlot(t,i){let e={left:t.position.x,right:t.position.x+i,bottom:t.position.y,top:t.position.y+i};this.removeSlot(t);for(let o=t.position.y;o<e.top;o++){let s=this.getRow({x:t.position.x,y:o});if(null!==s){let n=[],r=0;for(let i of s.slots)if(!(i.position.x+i.r<e.left||i.position.x>=e.right)){n.push(i);let e=Math.max(0,i.position.x+i.r-(t.position.x+t.r));r=Math.max(r,e)}e.right<this.width&&!s.map.hasOwnProperty(e.right)&&this.addSlot({position:{x:e.right,y:o},r:t.r-i+r});for(let i of n)i.r=t.position.x-i.position.x,0===i.r&&this.removeSlot(i)}else this.addRow(),t.position.x>0&&this.addSlot({position:{x:0,y:o},r:t.position.x}),e.right<this.width&&this.addSlot({position:{x:e.right,y:o},r:this.width-e.right})}for(let e=Math.max(0,t.position.y-i);e<t.position.y;e++){let o=this.getRow({x:t.position.x,y:e});if(null!==o)for(let e=0;e<o.slots.length;e++){let s=o.slots[e];if(s.position.x<t.position.x+i&&s.position.x+s.r>t.position.x&&s.position.y+s.r>=t.position.y){let i=s.r;s.r=t.position.y-s.position.y;let e={x:s.position.x+s.r,y:s.position.y,width:i-s.r,height:s.r};for(;e.width>0&&e.height>0;)e.width<=e.height?(this.addSlot({position:{x:e.x,y:e.y},r:e.width}),e.y+=e.width,e.height-=e.width):(this.addSlot({position:{x:e.x,y:e.y},r:e.height}),e.x+=e.height,e.width-=e.height)}}}return{position:t.position,r:i}}place(t){let i={},e=!1,o=null;for(let i of this.rows){for(let s of i.slots)if(s.r>=t){e=!0,o=this.fillSlot(s,t);break}if(e)break}if(!e){let i=this.addRow(),e=this.addSlot({position:{x:0,y:i.y},r:this.width});o=this.fillSlot(e,t)}for(let t=0;t<o.r;t++)for(let e=0;e<o.r;e++)this.setTxMapCell({x:o.position.x+t,y:o.position.y+e},i);return o.position.x+o.r>this.xMax&&(this.xMax=o.position.x+o.r),o.position.y+o.r>this.yMax&&(this.yMax=o.position.y+o.r),o}setTxMapCell(t,i){let e=t.y-this.rowOffset;if(e>=0&&e<this.height&&t.x>=0&&t.x<this.width){let o=e*this.width+t.x;o>=0&&o<this.txMap.length&&(this.txMap[o]=i)}}}