import{d as e,c as t,a as n,w as o,b as i,r as l,o as a,e as s,t as r,F as c,f as d,g as u,h as g,v as p,i as h,j as m,k as y,l as f,m as w,n as v,p as b,q as x,s as C}from"./vendor.b622ee49.js";var k=e({name:"app",computed:{showNav(){return!["game","replay"].includes(String(this.$route.name))}}});const A={id:"app"},z={key:0,class:"nav"},S=s("Index"),P=s("New game");k.render=function(e,s,r,c,d,u){const g=l("router-link"),p=l("router-view");return a(),t("div",A,[e.showNav?(a(),t("ul",z,[n("li",null,[n(g,{class:"btn",to:{name:"index"}},{default:o((()=>[S])),_:1})]),n("li",null,[n(g,{class:"btn",to:{name:"new-game"}},{default:o((()=>[P])),_:1})])])):i("",!0),n(p)])};const I=864e5,T=e=>{const t=Math.floor(e/I);e%=I;const n=Math.floor(e/36e5);e%=36e5;const o=Math.floor(e/6e4);e%=6e4;return`${t}d ${n}h ${o}m ${Math.floor(e/1e3)}s`};var _=1e3,D=()=>{const e=new Date;return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds())},B=(e,t)=>T(t-e),E=T,O=e({name:"game-teaser",props:{game:{type:Object,required:!0}},computed:{style(){return{"background-image":`url("${this.game.imageUrl.replace("uploads/","uploads/r/")+"-375x210.webp"}")`}}},methods:{time(e,t){const n=t?"🏁":"âŗ",o=e,i=t||D();return`${n} ${B(o,i)}`}}});const N={class:"game-info-text"},U=n("br",null,null,-1),M=n("br",null,null,-1),G=n("br",null,null,-1),$=s(" â†Ēī¸ Watch replay ");O.render=function(e,c,d,u,g,p){const h=l("router-link");return a(),t("div",{class:"game-teaser",style:e.style},[n(h,{class:"game-info",to:{name:"game",params:{id:e.game.id}}},{default:o((()=>[n("span",N,[s(" 🧩 "+r(e.game.tilesFinished)+"/"+r(e.game.tilesTotal),1),U,s(" đŸ‘Ĩ "+r(e.game.players),1),M,s(" "+r(e.time(e.game.started,e.game.finished)),1),G])])),_:1},8,["to"]),e.game.hasReplay?(a(),t(h,{key:0,class:"game-replay",to:{name:"replay",params:{id:e.game.id}}},{default:o((()=>[$])),_:1},8,["to"])):i("",!0)],4)};var R=e({components:{GameTeaser:O},data:()=>({gamesRunning:[],gamesFinished:[]}),async created(){const e=await fetch("/api/index-data"),t=await e.json();this.gamesRunning=t.gamesRunning,this.gamesFinished=t.gamesFinished}});const V=n("h1",null,"Running games",-1),j=n("h1",null,"Finished games",-1);R.render=function(e,o,i,s,r,u){const g=l("game-teaser");return a(),t("div",null,[V,(a(!0),t(c,null,d(e.gamesRunning,((e,o)=>(a(),t("div",{class:"game-teaser-wrap",key:o},[n(g,{game:e},null,8,["game"])])))),128)),j,(a(!0),t(c,null,d(e.gamesFinished,((e,o)=>(a(),t("div",{class:"game-teaser-wrap",key:o},[n(g,{game:e},null,8,["game"])])))),128))])};var F=e({name:"image-teaser",props:{image:{type:Object,required:!0}},computed:{style(){return{backgroundImage:`url("${this.image.url.replace("uploads/","uploads/r/")+"-150x100.webp"}")`}}},emits:{click:null,editClick:null},methods:{onClick(){this.$emit("click")},onEditClick(){this.$emit("editClick")}}});F.render=function(e,o,i,l,s,r){return a(),t("div",{class:"imageteaser",style:e.style,onClick:o[2]||(o[2]=(...t)=>e.onClick&&e.onClick(...t))},[n("div",{class:"btn edit",onClick:o[1]||(o[1]=u(((...t)=>e.onEditClick&&e.onEditClick(...t)),["stop"]))},"âœī¸")],4)};var L=e({name:"image-library",components:{ImageTeaser:F},props:{images:{type:Array,required:!0}},emits:{imageClicked:null,imageEditClicked:null},methods:{imageClicked(e){this.$emit("imageClicked",e)},imageEditClicked(e){this.$emit("imageEditClicked",e)}}});L.render=function(e,n,o,i,s,r){const u=l("image-teaser");return a(),t("div",null,[(a(!0),t(c,null,d(e.images,((n,o)=>(a(),t(u,{image:n,onClick:t=>e.imageClicked(n),onEditClick:t=>e.imageEditClicked(n),key:o},null,8,["image","onClick","onEditClick"])))),128))])};const W={name:"responsive-image",props:{src:String,title:{type:String,default:""},height:{type:String,default:"100%"},width:{type:String,default:"100%"}},computed:{style(){return{display:"inline-block",verticalAlign:"text-bottom",backgroundImage:`url('${this.src}')`,backgroundRepeat:"no-repeat",backgroundSize:"contain",backgroundPosition:"center",width:this.width,height:this.height}}}};W.render=function(e,n,o,i,l,s){return a(),t("div",{style:s.style,title:o.title},null,12,["title"])};var q=e({name:"tags-input",props:{modelValue:{type:Array,required:!0}},emits:{"update:modelValue":null},data:()=>({input:"",values:[]}),created(){this.values=this.modelValue},methods:{onKeyUp(e){if(","===e.key)return this.add(),e.stopPropagation(),!1},add(){const e=this.input.replace(/,/g,"").trim();e&&(this.values.includes(e)||this.values.push(e),this.input="",this.$emit("update:modelValue",this.values))},rm(e){this.values=this.values.filter((t=>t!==e)),this.$emit("update:modelValue",this.values)}}});const H=m()(((e,o,i,l,s,u)=>(a(),t("div",null,[g(n("input",{class:"input",type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.input=t),placeholder:"Plants, People",onKeydown:o[2]||(o[2]=h(((...t)=>e.add&&e.add(...t)),["enter"])),onKeyup:o[3]||(o[3]=(...t)=>e.onKeyUp&&e.onKeyUp(...t))},null,544),[[p,e.input]]),(a(!0),t(c,null,d(e.values,((n,o)=>(a(),t("span",{key:o,class:"bit",onClick:t=>e.rm(n)},r(n)+" ✖",9,["onClick"])))),128))]))));q.render=H,q.__scopeId="data-v-771460ae";var Q=e({name:"new-image-dialog",components:{ResponsiveImage:W,TagsInput:q},emits:{bgclick:null,setupGameClick:null,postToGalleryClick:null},data:()=>({previewUrl:"",file:null,title:"",tags:[]}),computed:{canPostToGallery(){return!(!this.previewUrl||!this.file)},canSetupGameClick(){return!(!this.previewUrl||!this.file)}},methods:{preview(e){const t=e.target;if(!t.files)return;const n=t.files[0];if(!n)return;const o=new FileReader;o.readAsDataURL(n),o.onload=e=>{this.previewUrl=e.target.result,this.file=n}},postToGallery(){this.$emit("postToGalleryClick",{file:this.file,title:this.title,tags:this.tags})},setupGameClick(){this.$emit("setupGameClick",{file:this.file,title:this.title,tags:this.tags})}}});const Y={key:0,class:"has-image"},K={key:1},Z={class:"upload"},J=n("span",{class:"btn"},"Upload File",-1),X={class:"area-settings"},ee=n("td",null,[n("label",null,"Title")],-1),te=n("tr",null,[n("td",{colspan:"2"},[n("div",{class:"hint"},"Feel free to leave a credit to the artist/photographer in the title :)")])],-1),ne=n("td",null,[n("label",null,"Tags")],-1),oe={class:"area-buttons"},ie=s("🧩 Post to gallery "),le=n("br",null,null,-1),ae=s(" + set up game");Q.render=function(e,o,i,s,r,c){const d=l("responsive-image"),h=l("tags-input");return a(),t("div",{class:"overlay new-image-dialog",onClick:o[8]||(o[8]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[7]||(o[7]=u((()=>{}),["stop"]))},[n("div",{class:["area-image",{"has-image":!!e.previewUrl,"no-image":!e.previewUrl}]},[e.previewUrl?(a(),t("div",Y,[n("span",{class:"remove btn",onClick:o[1]||(o[1]=t=>e.previewUrl="")},"X"),n(d,{src:e.previewUrl},null,8,["src"])])):(a(),t("div",K,[n("label",Z,[n("input",{type:"file",style:{display:"none"},onChange:o[2]||(o[2]=(...t)=>e.preview&&e.preview(...t)),accept:"image/*"},null,32),J])]))],2),n("div",X,[n("table",null,[n("tr",null,[ee,n("td",null,[g(n("input",{type:"text","onUpdate:modelValue":o[3]||(o[3]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[p,e.title]])])]),te,n("tr",null,[ne,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[4]||(o[4]=t=>e.tags=t)},null,8,["modelValue"])])])])]),n("div",oe,[n("button",{class:"btn",disabled:!e.canPostToGallery,onClick:o[5]||(o[5]=(...t)=>e.postToGallery&&e.postToGallery(...t))},"đŸ–ŧī¸ Post to gallery",8,["disabled"]),n("button",{class:"btn",disabled:!e.canSetupGameClick,onClick:o[6]||(o[6]=(...t)=>e.setupGameClick&&e.setupGameClick(...t))},[ie,le,ae],8,["disabled"])])])])};var se=e({name:"edit-image-dialog",components:{ResponsiveImage:W,TagsInput:q},props:{image:{type:Object,required:!0}},emits:{bgclick:null,saveClick:null},data:()=>({title:"",tags:[]}),created(){this.title=this.image.title,this.tags=this.image.tags.map((e=>e.title))},methods:{saveImage(){this.$emit("saveClick",{id:this.image.id,title:this.title,tags:this.tags})}}});const re={class:"area-image"},ce={class:"has-image"},de={class:"area-settings"},ue=n("td",null,[n("label",null,"Title")],-1),ge=n("tr",null,[n("td",{colspan:"2"},[n("div",{class:"hint"},"Feel free to leave a credit to the artist/photographer in the title :)")])],-1),pe=n("td",null,[n("label",null,"Tags")],-1),he={class:"area-buttons"};var me,ye,fe,we;se.render=function(e,o,i,s,r,c){const d=l("responsive-image"),h=l("tags-input");return a(),t("div",{class:"overlay edit-image-dialog",onClick:o[5]||(o[5]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[4]||(o[4]=u((()=>{}),["stop"]))},[n("div",re,[n("div",ce,[n(d,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",de,[n("table",null,[n("tr",null,[ue,n("td",null,[g(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[p,e.title]])])]),ge,n("tr",null,[pe,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[2]||(o[2]=t=>e.tags=t)},null,8,["modelValue"])])])])]),n("div",he,[n("button",{class:"btn",onClick:o[3]||(o[3]=(...t)=>e.saveImage&&e.saveImage(...t))},"đŸ–ŧī¸ Save image")])])])},(ye=me||(me={}))[ye.Flat=0]="Flat",ye[ye.Out=1]="Out",ye[ye.In=-1]="In",(we=fe||(fe={}))[we.FINAL=0]="FINAL",we[we.ANY=1]="ANY";var ve=e({name:"new-game-dialog",components:{ResponsiveImage:W},props:{image:{type:Object,required:!0}},emits:{newGame:null,bgclick:null},data:()=>({tiles:1e3,scoreMode:fe.ANY}),methods:{onNewGameClick(){this.$emit("newGame",{tiles:this.tilesInt,image:this.image,scoreMode:this.scoreModeInt})}},computed:{canStartNewGame(){return!!(this.tilesInt&&this.image&&this.image.url&&[0,1].includes(this.scoreModeInt))},scoreModeInt(){return parseInt(`${this.scoreMode}`,10)},tilesInt(){return parseInt(`${this.tiles}`,10)}}});const be={class:"area-image"},xe={class:"has-image"},Ce={class:"area-settings"},ke=n("td",null,[n("label",null,"Pieces")],-1),Ae=n("td",null,[n("label",null,"Scoring: ")],-1),ze=s(" Any (Score when pieces are connected to each other or on final location)"),Se=n("br",null,null,-1),Pe=s(" Final (Score when pieces are put to their final location)"),Ie={class:"area-buttons"};ve.render=function(e,o,i,s,r,c){const d=l("responsive-image");return a(),t("div",{class:"overlay new-game-dialog",onClick:o[6]||(o[6]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[5]||(o[5]=u((()=>{}),["stop"]))},[n("div",be,[n("div",xe,[n(d,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",Ce,[n("table",null,[n("tr",null,[ke,n("td",null,[g(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.tiles=t)},null,512),[[p,e.tiles]])])]),n("tr",null,[Ae,n("td",null,[n("label",null,[g(n("input",{type:"radio","onUpdate:modelValue":o[2]||(o[2]=t=>e.scoreMode=t),value:"1"},null,512),[[y,e.scoreMode]]),ze]),Se,n("label",null,[g(n("input",{type:"radio","onUpdate:modelValue":o[3]||(o[3]=t=>e.scoreMode=t),value:"0"},null,512),[[y,e.scoreMode]]),Pe])])])])]),n("div",Ie,[n("button",{class:"btn",disabled:!e.canStartNewGame,onClick:o[4]||(o[4]=(...t)=>e.onNewGameClick&&e.onNewGameClick(...t))}," 🧩 Generate Puzzle ",8,["disabled"])])])])};class Te{constructor(e){this.rand_high=e||3735929054,this.rand_low=1231121986^e}random(e,t){this.rand_high=(this.rand_high<<16)+(this.rand_high>>16)+this.rand_low&4294967295,this.rand_low=this.rand_low+this.rand_high&4294967295;return e+(this.rand_high>>>0)/4294967295*(t-e+1)|0}choice(e){return e[this.random(0,e.length-1)]}shuffle(e){const t=e.slice();for(let n=0;n<=t.length-2;n++){const e=this.random(n,t.length-1),o=t[n];t[n]=t[e],t[e]=o}return t}static serialize(e){return{rand_high:e.rand_high,rand_low:e.rand_low}}static unserialize(e){const t=new Te(0);return t.rand_high=e.rand_high,t.rand_low=e.rand_low,t}}const _e=(e,t)=>{const n=`${e}`;return n.length>=t.length?n:t.substr(0,t.length-n.length)+n},De=(...e)=>{const t=t=>(...n)=>{const o=new Date,i=_e(o.getHours(),"00"),l=_e(o.getMinutes(),"00"),a=_e(o.getSeconds(),"00");console[t](`${i}:${l}:${a}`,...e,...n)};return{log:t("log"),error:t("error"),info:t("info")}};var Be={hash:e=>{let t=0;for(let n=0;n{let t=e.toLowerCase();return t=t.replace(/[^a-z0-9]+/g,"-"),t=t.replace(/^-|-$/,""),t},uniqId:()=>Date.now().toString(36)+Math.random().toString(36).substring(2),encodeShape:function(e){return e.top+1<<0|e.right+1<<2|e.bottom+1<<4|e.left+1<<6},decodeShape:function(e){return{top:(e>>0&3)-1,right:(e>>2&3)-1,bottom:(e>>4&3)-1,left:(e>>6&3)-1}},encodePiece:function(e){return[e.idx,e.pos.x,e.pos.y,e.z,e.owner,e.group]},decodePiece:function(e){return{idx:e[0],pos:{x:e[1],y:e[2]},z:e[3],owner:e[4],group:e[5]}},encodePlayer:function(e){return[e.id,e.x,e.y,e.d,e.name,e.color,e.bgcolor,e.points,e.ts]},decodePlayer:function(e){return{id:e[0],x:e[1],y:e[2],d:e[3],name:e[4],color:e[5],bgcolor:e[6],points:e[7],ts:e[8]}},encodeGame:function(e){return[e.id,e.rng.type||"",Te.serialize(e.rng.obj),e.puzzle,e.players,e.evtInfos,e.scoreMode||fe.FINAL]},decodeGame:function(e){return{id:e[0],rng:{type:e[1],obj:Te.unserialize(e[2])},puzzle:e[3],players:e[4],evtInfos:e[5],scoreMode:e[6]}},coordByPieceIdx:function(e,t){const n=e.width/e.tileSize;return{x:t%n,y:Math.floor(t/n)}},asQueryArgs:function(e){const t=[];for(const n in e){const o=[n,e[n]].map(encodeURIComponent);t.push(o.join("="))}return 0===t.length?"":`?${t.join("&")}`}},Ee=e({components:{ImageLibrary:L,NewImageDialog:Q,EditImageDialog:se,NewGameDialog:ve},data:()=>({filters:{sort:"date_desc",tags:[]},images:[],tags:[],image:{id:0,filename:"",file:"",url:"",title:"",tags:[],created:0},dialog:""}),async created(){await this.loadImages()},methods:{toggleTag(e){this.filters.tags.includes(e.slug)?this.filters.tags=this.filters.tags.filter((t=>t!==e.slug)):this.filters.tags.push(e.slug),this.filtersChanged()},async loadImages(){const e=await fetch(`/api/newgame-data${Be.asQueryArgs(this.filters)}`),t=await e.json();this.images=t.images,this.tags=t.tags},async filtersChanged(){await this.loadImages()},onImageClicked(e){this.image=e,this.dialog="new-game"},onImageEditClicked(e){this.image=e,this.dialog="edit-image"},async uploadImage(e){const t=new FormData;t.append("file",e.file,e.file.name),t.append("title",e.title),t.append("tags",e.tags);const n=await fetch("/api/upload",{method:"post",body:t});return await n.json()},async saveImage(e){const t=await fetch("/api/save-image",{method:"post",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify({id:e.id,title:e.title,tags:e.tags})});return await t.json()},async onSaveImageClick(e){await this.saveImage(e),this.dialog="",await this.loadImages()},async postToGalleryClick(e){await this.uploadImage(e),this.dialog="",await this.loadImages()},async setupGameClick(e){const t=await this.uploadImage(e);this.loadImages(),this.image=t,this.dialog="new-game"},async onNewGame(e){const t=await fetch("/newgame",{method:"post",headers:{Accept:"application/json","Content-Type":"application/json"},body:JSON.stringify(e)});if(200===t.status){const e=await t.json();this.$router.push({name:"game",params:{id:e.id}})}}}});const Oe={class:"upload-image-teaser"},Ne=n("div",{class:"hint"},"(The image you upload will be added to the public gallery.)",-1),Ue={key:0},Me=s(" Tags: "),Ge=s(" Sort by: "),$e=n("option",{value:"date_desc"},"Newest first",-1),Re=n("option",{value:"date_asc"},"Oldest first",-1),Ve=n("option",{value:"alpha_asc"},"A-Z",-1),je=n("option",{value:"alpha_desc"},"Z-A",-1);Ee.render=function(e,o,s,u,p,h){const m=l("image-library"),y=l("new-image-dialog"),w=l("edit-image-dialog"),v=l("new-game-dialog");return a(),t("div",null,[n("div",Oe,[n("div",{class:"btn btn-big",onClick:o[1]||(o[1]=t=>e.dialog="new-image")},"Upload your image"),Ne]),n("div",null,[e.tags.length>0?(a(),t("label",Ue,[Me,(a(!0),t(c,null,d(e.tags,((n,o)=>(a(),t("span",{class:["bit",{on:e.filters.tags.includes(n.slug)}],key:o,onClick:t=>e.toggleTag(n)},r(n.title),11,["onClick"])))),128))])):i("",!0),n("label",null,[Ge,g(n("select",{"onUpdate:modelValue":o[2]||(o[2]=t=>e.filters.sort=t),onChange:o[3]||(o[3]=(...t)=>e.filtersChanged&&e.filtersChanged(...t))},[$e,Re,Ve,je],544),[[f,e.filters.sort]])])]),n(m,{images:e.images,onImageClicked:e.onImageClicked,onImageEditClicked:e.onImageEditClicked},null,8,["images","onImageClicked","onImageEditClicked"]),"new-image"===e.dialog?(a(),t(y,{key:0,onBgclick:o[4]||(o[4]=t=>e.dialog=""),onPostToGalleryClick:e.postToGalleryClick,onSetupGameClick:e.setupGameClick},null,8,["onPostToGalleryClick","onSetupGameClick"])):i("",!0),"edit-image"===e.dialog?(a(),t(w,{key:1,onBgclick:o[5]||(o[5]=t=>e.dialog=""),onSaveClick:e.onSaveImageClick,image:e.image},null,8,["onSaveClick","image"])):i("",!0),e.image&&"new-game"===e.dialog?(a(),t(v,{key:2,onBgclick:o[6]||(o[6]=t=>e.dialog=""),onNewGame:e.onNewGame,image:e.image},null,8,["onNewGame","image"])):i("",!0)])};var Fe=e({name:"scores",props:{activePlayers:{type:Array,required:!0},idlePlayers:{type:Array,required:!0}},computed:{actives(){return this.activePlayers.sort(((e,t)=>t.points-e.points)),this.activePlayers},idles(){return this.idlePlayers.sort(((e,t)=>t.points-e.points)),this.idlePlayers}}});const Le={class:"scores"},We=n("div",null,"Scores",-1),qe=n("td",null,"⚡",-1),He=n("td",null,"💤",-1);Fe.render=function(e,o,i,l,s,u){return a(),t("div",Le,[We,n("table",null,[(a(!0),t(c,null,d(e.actives,((e,o)=>(a(),t("tr",{key:o,style:{color:e.color}},[qe,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128)),(a(!0),t(c,null,d(e.idles,((e,o)=>(a(),t("tr",{key:o,style:{color:e.color}},[He,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128))])])};var Qe=e({name:"puzzle-status",props:{finished:{type:Boolean,required:!0},duration:{type:Number,required:!0},piecesDone:{type:Number,required:!0},piecesTotal:{type:Number,required:!0}},computed:{icon(){return this.finished?"🏁":"âŗ"},durationStr(){return E(this.duration)}}});const Ye={class:"timer"};Qe.render=function(e,o,i,l,s,c){return a(),t("div",Ye,[n("div",null," 🧩 "+r(e.piecesDone)+"/"+r(e.piecesTotal),1),n("div",null,r(e.icon)+" "+r(e.durationStr),1),w(e.$slots,"default")])};var Ke=e({name:"settings-overlay",emits:{bgclick:null,"update:modelValue":null},props:{modelValue:Object},created(){this.$watch("modelValue",(e=>{this.$emit("update:modelValue",e)}),{deep:!0})}});const Ze=n("td",null,[n("label",null,"Background: ")],-1),Je=n("td",null,[n("label",null,"Color: ")],-1),Xe=n("td",null,[n("label",null,"Name: ")],-1);Ke.render=function(e,o,i,l,s,r){return a(),t("div",{class:"overlay transparent",onClick:o[5]||(o[5]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content settings",onClick:o[4]||(o[4]=u((()=>{}),["stop"]))},[n("tr",null,[Ze,n("td",null,[g(n("input",{type:"color","onUpdate:modelValue":o[1]||(o[1]=t=>e.modelValue.background=t)},null,512),[[p,e.modelValue.background]])])]),n("tr",null,[Je,n("td",null,[g(n("input",{type:"color","onUpdate:modelValue":o[2]||(o[2]=t=>e.modelValue.color=t)},null,512),[[p,e.modelValue.color]])])]),n("tr",null,[Xe,n("td",null,[g(n("input",{type:"text",maxLength:"16","onUpdate:modelValue":o[3]||(o[3]=t=>e.modelValue.name=t)},null,512),[[p,e.modelValue.name]])])])])])};var et=e({name:"preview-overlay",props:{img:String},emits:{bgclick:null},computed:{previewStyle(){return{backgroundImage:`url('${this.img}')`}}}});const tt={class:"preview"};et.render=function(e,o,i,l,s,r){return a(),t("div",{class:"overlay",onClick:o[1]||(o[1]=t=>e.$emit("bgclick"))},[n("div",tt,[n("div",{class:"img",style:e.previewStyle},null,4)])])};var nt=1,ot=4,it=2,lt=3,at=2,st=4,rt=3,ct=9,dt=1,ut=2,gt=3,pt=4,ht=5,mt=6,yt=7,ft=8,wt=10,vt=1,bt=2,xt=3;const Ct=De("Communication.js");let kt,At=e=>{},zt=e=>{};let St=0;const Pt=e=>{St!==e&&(St=e,zt(e))};function It(e){if(2===St)try{kt.send(JSON.stringify(e))}catch(t){Ct.info("unable to send message.. maybe because ws is invalid?")}}let Tt,_t;var Dt={connect:function(e,t,n){return Tt=0,_t={},Pt(3),new Promise((o=>{kt=new WebSocket(e,n+"|"+t),kt.onopen=()=>{Pt(2),It([lt])},kt.onmessage=e=>{const t=JSON.parse(e.data),i=t[0];if(i===ot){const e=t[1];o(e)}else{if(i!==nt)throw`[ 2021-05-09 invalid connect msgType ${i} ]`;{const e=t[1],o=t[2];if(e===n&&_t[o])return void delete _t[o];At(t)}}},kt.onerror=()=>{throw Pt(1),"[ 2021-05-15 onerror ]"},kt.onclose=e=>{4e3===e.code||1001===e.code?Pt(4):Pt(1)}}))},requestReplayData:async function(e,t,n){const o={gameId:e,offset:t,size:n},i=await fetch(`/api/replay-data${Be.asQueryArgs(o)}`);return await i.json()},disconnect:function(){kt&&kt.close(4e3),Tt=0,_t={}},sendClientEvent:function(e){Tt++,_t[Tt]=e,It([it,Tt,_t[Tt]])},onServerChange:function(e){At=e},onConnectionStateChange:function(e){zt=e},CODE_CUSTOM_DISCONNECT:4e3,CONN_STATE_NOT_CONNECTED:0,CONN_STATE_DISCONNECTED:1,CONN_STATE_CLOSED:4,CONN_STATE_CONNECTED:2,CONN_STATE_CONNECTING:3},Bt=e({name:"connection-overlay",emits:{reconnect:null},props:{connectionState:Number},computed:{lostConnection(){return this.connectionState===Dt.CONN_STATE_DISCONNECTED},connecting(){return this.connectionState===Dt.CONN_STATE_CONNECTING},show(){return!(!this.lostConnection&&!this.connecting)}}});const Et={key:0,class:"overlay connection-lost"},Ot={key:0,class:"overlay-content"},Nt=n("div",null,"â‰ī¸ LOST CONNECTION â‰ī¸",-1),Ut={key:1,class:"overlay-content"},Mt=n("div",null,"Connecting...",-1);Bt.render=function(e,o,l,s,r,c){return e.show?(a(),t("div",Et,[e.lostConnection?(a(),t("div",Ot,[Nt,n("span",{class:"btn",onClick:o[1]||(o[1]=t=>e.$emit("reconnect"))},"Reconnect")])):i("",!0),e.connecting?(a(),t("div",Ut,[Mt])):i("",!0)])):i("",!0)};var Gt=e({name:"help-overlay",emits:{bgclick:null}});const $t=n("tr",null,[n("td",null,"âŦ†ī¸ Move up:"),n("td",null,[n("div",null,[n("kbd",null,"W"),s("/"),n("kbd",null,"↑"),s("/đŸ–ąī¸")])])],-1),Rt=n("tr",null,[n("td",null,"âŦ‡ī¸ Move down:"),n("td",null,[n("div",null,[n("kbd",null,"S"),s("/"),n("kbd",null,"↓"),s("/đŸ–ąī¸")])])],-1),Vt=n("tr",null,[n("td",null,"âŦ…ī¸ Move left:"),n("td",null,[n("div",null,[n("kbd",null,"A"),s("/"),n("kbd",null,"←"),s("/đŸ–ąī¸")])])],-1),jt=n("tr",null,[n("td",null,"âžĄī¸ Move right:"),n("td",null,[n("div",null,[n("kbd",null,"D"),s("/"),n("kbd",null,"→"),s("/đŸ–ąī¸")])])],-1),Ft=n("tr",null,[n("td"),n("td",null,[n("div",null,[s("Move faster by holding "),n("kbd",null,"Shift")])])],-1),Lt=n("tr",null,[n("td",null,"🔍+ Zoom in:"),n("td",null,[n("div",null,[n("kbd",null,"E"),s("/đŸ–ąī¸-Wheel")])])],-1),Wt=n("tr",null,[n("td",null,"🔍- Zoom out:"),n("td",null,[n("div",null,[n("kbd",null,"Q"),s("/đŸ–ąī¸-Wheel")])])],-1),qt=n("tr",null,[n("td",null,"đŸ–ŧī¸ Toggle preview:"),n("td",null,[n("div",null,[n("kbd",null,"Space")])])],-1),Ht=n("tr",null,[n("td",null,"đŸ§Šâœ”ī¸ Toggle fixed pieces:"),n("td",null,[n("div",null,[n("kbd",null,"F")])])],-1),Qt=n("tr",null,[n("td",null,"🧩❓ Toggle loose pieces:"),n("td",null,[n("div",null,[n("kbd",null,"G")])])],-1);Gt.render=function(e,o,i,l,s,r){return a(),t("div",{class:"overlay transparent",onClick:o[2]||(o[2]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content help",onClick:o[1]||(o[1]=u((()=>{}),["stop"]))},[$t,Rt,Vt,jt,Ft,Lt,Wt,qt,Ht,Qt])])};var Yt=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAW0lEQVQ4je1RywrAIAxLxP//5exixRWlVgZelpOKeTQFfnDypgy3eLIkSLLL8mxGPoHsU2hPAgDHBLvRX6hZZw/fwT0BtlLSONqCbWAmEIqMZOCDDlaDR3N03gOyDCn+y4DWmAAAAABJRU5ErkJggg=="}),Kt=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARElEQVQ4jWNgGAU0Af+hmBCbgYGBgYERhwHEAEYGBgYGJtIdiApYyLAZBVDsAqoagC1ACQJyY4ERg0GCISh6KA4DigEAou8LC+LnIJoAAAAASUVORK5CYII="}),Zt=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVQ4ja1TQQ7AIAgD///n7jCozA2Hbk00jbG1KIrcARszTugoBs49qioZj7r2kKACptkyAOCJsJuA+GzglwHjvMSSWFVaENWVASxh5eRLiq5fN/ASjI89VcP2K3hHpq1cEXNaMfnrL3TDZP2tDuoOA6MzCCXWr38AAAAASUVORK5CYII="}),Jt=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAU0lEQVQ4jWNgoAH4D8X42HDARKlt5BoAd82AuQAOGLGIYQQUPv0wF5CiCQUge4EsQ5C9QI4BjMguwBYeBAElscCIy1ZivMKIwSDBEBQ9FCckigEAU3QOD7TGvY4AAAAASUVORK5CYII="});function Xt(){let e=0,t=0,n=1;const o=(o,i)=>{e+=o/n,t+=i/n},i=e=>{const t=n+.05*n*("in"===e?1:-1);return Math.min(Math.max(t,.1),6)},l=o=>({x:o.x/n-e,y:o.y/n-t}),a=o=>({x:(o.x+e)*n,y:(o.y+t)*n}),s=e=>({w:e.w*n,h:e.h*n});return{move:o,canZoom:e=>n!=i(e),zoom:(e,t)=>((e,t)=>{if(n==e)return!1;const i=1-n/e;return o(-t.x*i,-t.y*i),n=e,!0})(i(e),t),worldToViewport:e=>{const{x:t,y:n}=a(e);return{x:Math.round(t),y:Math.round(n)}},worldToViewportRaw:a,worldDimToViewport:e=>{const{w:t,h:n}=s(e);return{w:Math.round(t),h:Math.round(n)}},worldDimToViewportRaw:s,viewportToWorld:e=>{const{x:t,y:n}=l(e);return{x:Math.round(t),y:Math.round(n)}},viewportToWorldRaw:l}}function en(e=0,t=0){const n=document.createElement("canvas");return n.width=e,n.height=t,n}var tn={createCanvas:en,loadImageToBitmap:async function(e){return new Promise((t=>{const n=new Image;n.onload=()=>{createImageBitmap(n).then(t)},n.src=e}))},resizeBitmap:async function(e,t,n){const o=en(t,n);return o.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,t,n),await createImageBitmap(o)},colorizedCanvas:function(e,t,n){const o=en(e.width,e.height),i=o.getContext("2d");return i.save(),i.drawImage(t,0,0),i.fillStyle=n,i.globalCompositeOperation="source-in",i.fillRect(0,0,t.width,t.height),i.restore(),i.save(),i.globalCompositeOperation="destination-over",i.drawImage(e,0,0),i.restore(),o}};const nn=De("Debug.js");let on=0,ln=0;var an=e=>{on=performance.now(),ln=e},sn=e=>{const t=performance.now(),n=t-on;n>ln&&nn.log(e+": "+n),on=t};function rn(e,t){const n=e.x-t.x,o=e.y-t.y;return Math.sqrt(n*n+o*o)}function cn(e){return{x:e.x+e.w/2,y:e.y+e.h/2}}var dn={pointSub:function(e,t){return{x:e.x-t.x,y:e.y-t.y}},pointAdd:function(e,t){return{x:e.x+t.x,y:e.y+t.y}},pointDistance:rn,pointInBounds:function(e,t){return e.x>=t.x&&e.x<=t.x+t.w&&e.y>=t.y&&e.y<=t.y+t.h},rectCenter:cn,rectMoved:function(e,t,n){return{x:e.x+t,y:e.y+n,w:e.w,h:e.h}},rectCenterDistance:function(e,t){return rn(cn(e),cn(t))},rectsOverlap:function(e,t){return!(t.x>e.x+e.w||e.x>t.x+t.w||t.y>e.y+e.h||e.y>t.y+t.h)}};const un=De("PuzzleGraphics.js");function gn(e,t){const n=Be.coordByPieceIdx(e,t);return{x:n.x*e.tileSize,y:n.y*e.tileSize,w:e.tileSize,h:e.tileSize}}var pn={loadPuzzleBitmaps:async function(e){const t=await tn.loadImageToBitmap(e.info.imageUrl),n=await tn.resizeBitmap(t,e.info.width,e.info.height);return await async function(e,t,n){un.log("start createPuzzleTileBitmaps");const o=n.tileSize,i=n.tileMarginWidth,l=n.tileDrawSize,a=o/100,s=[0,0,40,15,37,5,37,5,40,0,38,-5,38,-5,20,-20,50,-20,50,-20,80,-20,62,-5,62,-5,60,0,63,5,63,5,65,15,100,0],r=new Array(t.length),c={};function d(e){const t=`${e.top}${e.right}${e.left}${e.bottom}`;if(c[t])return c[t];const n=new Path2D,l={x:i,y:i},r=dn.pointAdd(l,{x:o,y:0}),d=dn.pointAdd(r,{x:0,y:o}),u=dn.pointSub(d,{x:o,y:0});if(n.moveTo(l.x,l.y),0!==e.top)for(let o=0;oBe.decodePiece(hn[e].puzzle.tiles[t]),In=(e,t)=>Pn(e,t).group,Tn=(e,t)=>{const n=hn[e].puzzle.info,o={x:(n.table.width-n.width)/2,y:(n.table.height-n.height)/2},i=function(e,t){const n=hn[e].puzzle.info,o=Be.coordByPieceIdx(n,t),i=o.x*n.tileSize,l=o.y*n.tileSize;return{x:i,y:l}}(e,t);return dn.pointAdd(o,i)},_n=(e,t)=>Pn(e,t).pos,Dn=e=>{const t=qn(e),n=Hn(e),o=Math.round(t/4),i=Math.round(n/4);return{x:0-o,y:0-i,w:t+2*o,h:n+2*i}},Bn=(e,t)=>{const n=Un(e),o=Pn(e,t);return{x:o.pos.x,y:o.pos.y,w:n,h:n}},En=(e,t)=>Pn(e,t).z,On=(e,t)=>{for(const n of hn[e].puzzle.tiles){const e=Be.decodePiece(n);if(e.owner===t)return e.idx}return-1},Nn=e=>hn[e].puzzle.info.tileDrawSize,Un=e=>hn[e].puzzle.info.tileSize,Mn=e=>hn[e].puzzle.data.maxGroup,Gn=e=>hn[e].puzzle.data.maxZ;function $n(e,t){const n=hn[e].puzzle.info,o=Be.coordByPieceIdx(n,t);return[o.y>0?t-n.tilesX:-1,o.x0?t-1:-1]}const Rn=(e,t,n)=>{for(const o of t)Sn(e,o,{z:n})},Vn=(e,t,n)=>{const o=_n(e,t);Sn(e,t,{pos:dn.pointAdd(o,n)})},jn=(e,t,n)=>{const o=Nn(e),i=Dn(e),l=n;for(const a of t){const t=Pn(e,a);t.pos.x+n.xi.x+i.w&&(l.x=Math.min(i.x+i.w-t.pos.x+o,l.x)),t.pos.y+n.yi.y+i.h&&(l.y=Math.min(i.y+i.h-t.pos.y+o,l.y))}for(const a of t)Vn(e,a,l)},Fn=(e,t,n)=>{for(const o of t)Sn(e,o,{owner:n})};function Ln(e,t){const n=hn[e].puzzle.tiles,o=Be.decodePiece(n[t]),i=[];if(o.group)for(const l of n){const e=Be.decodePiece(l);e.group===o.group&&i.push(e.idx)}else i.push(o.idx);return i}const Wn=(e,t)=>{const n=yn(e,t);return n?n.points:0},qn=e=>hn[e].puzzle.info.table.width,Hn=e=>hn[e].puzzle.info.table.height;var Qn={setGame:function(e,t){hn[e]=t},exists:function(e){return!!hn[e]||!1},playerExists:wn,getActivePlayers:function(e,t){const n=t-30*_;return vn(e).filter((e=>e.ts>=n))},getIdlePlayers:function(e,t){const n=t-30*_;return vn(e).filter((e=>e.ts0))},addPlayer:function(e,t,n){wn(e,t)?An(e,t,{ts:n}):fn(e,t,function(e,t){return{id:e,x:0,y:0,d:0,name:null,color:null,bgcolor:null,points:0,ts:t}}(t,n))},getFinishedPiecesCount:kn,getPieceCount:bn,getImageUrl:function(e){return hn[e].puzzle.info.imageUrl},setImageUrl:function(e,t){hn[e].puzzle.info.imageUrl=t},get:function(e){return hn[e]||null},getAllGames:function(){return Object.values(hn).sort(((e,t)=>Cn(e.id)===Cn(t.id)?t.puzzle.data.started-e.puzzle.data.started:Cn(e.id)?1:-1))},getPlayerBgColor:(e,t)=>{const n=yn(e,t);return n?n.bgcolor:null},getPlayerColor:(e,t)=>{const n=yn(e,t);return n?n.color:null},getPlayerName:(e,t)=>{const n=yn(e,t);return n?n.name:null},getPlayerIndexById:mn,getPlayerIdByIndex:function(e,t){return hn[e].players.length>t?Be.decodePlayer(hn[e].players[t]).id:null},changePlayer:An,setPlayer:fn,setPiece:function(e,t,n){hn[e].puzzle.tiles[t]=Be.encodePiece(n)},setPuzzleData:function(e,t){hn[e].puzzle.data=t},getTableWidth:qn,getTableHeight:Hn,getPuzzle:e=>hn[e].puzzle,getRng:e=>hn[e].rng.obj,getPuzzleWidth:e=>hn[e].puzzle.info.width,getPuzzleHeight:e=>hn[e].puzzle.info.height,getPiecesSortedByZIndex:function(e){return hn[e].puzzle.tiles.map(Be.decodePiece).sort(((e,t)=>e.z-t.z))},getFirstOwnedPiece:(e,t)=>{const n=On(e,t);return n<0?null:hn[e].puzzle.tiles[n]},getPieceDrawOffset:e=>hn[e].puzzle.info.tileDrawOffset,getPieceDrawSize:Nn,getFinalPiecePos:Tn,getStartTs:e=>hn[e].puzzle.data.started,getFinishTs:e=>hn[e].puzzle.data.finished,handleInput:function(e,t,n,o){const i=hn[e].puzzle,l=function(e,t){return t in hn[e].evtInfos?hn[e].evtInfos[t]:{_last_mouse:null,_last_mouse_down:null}}(e,t),a=[],s=()=>{a.push([vt,i.data])},r=t=>{a.push([bt,Be.encodePiece(Pn(e,t))])},c=e=>{for(const t of e)r(t)},d=()=>{const n=yn(e,t);n&&a.push([xt,Be.encodePlayer(n)])},u=n[0];if(u===mt){const i=n[1];An(e,t,{bgcolor:i,ts:o}),d()}else if(u===yt){const i=n[1];An(e,t,{color:i,ts:o}),d()}else if(u===ft){const i=`${n[1]}`.substr(0,16);An(e,t,{name:i,ts:o}),d()}else if(u===dt){const i={x:n[1],y:n[2]};An(e,t,{d:1,ts:o}),d(),l._last_mouse_down=i;const a=((e,t)=>{const n=hn[e].puzzle.info,o=hn[e].puzzle.tiles;let i=-1,l=-1;for(let a=0;ai)&&(i=e.z,l=a)}return l})(e,i);if(a>=0){const n=Gn(e)+1;zn(e,{maxZ:n}),s();const o=Ln(e,a);Rn(e,o,Gn(e)),Fn(e,o,t),c(o)}l._last_mouse=i}else if(u===gt){const i=n[1],a=n[2],s={x:i,y:a};if(null===l._last_mouse_down)An(e,t,{x:i,y:a,ts:o}),d();else{const n=On(e,t);if(n>=0){An(e,t,{x:i,y:a,ts:o}),d();const r=Ln(e,n);let u=dn.pointInBounds(s,Dn(e))&&dn.pointInBounds(l._last_mouse_down,Dn(e));for(const t of r){const n=Bn(e,t);if(dn.pointInBounds(s,n)){u=!0;break}}if(u){const t=i-l._last_mouse_down.x,n=a-l._last_mouse_down.y;jn(e,r,{x:t,y:n}),c(r)}}else An(e,t,{ts:o}),d();l._last_mouse_down=s}l._last_mouse=s}else if(u===ut){const a={x:n[1],y:n[2]},u=0;l._last_mouse_down=null;const g=On(e,t);if(g>=0){const n=Ln(e,g);Fn(e,n,0),c(n);const l=_n(e,g),a=Tn(e,g);if(dn.pointDistance(a,l){for(const n of t)Sn(e,n,{owner:-1,z:1})})(e,n),c(n);let r=Wn(e,t);xn(e)===fe.FINAL?r+=n.length:xn(e)===fe.ANY&&(r+=1),An(e,t,{d:u,ts:o,points:r}),d(),kn(e)===bn(e)&&(zn(e,{finished:o}),s())}else{const n=(e,t,n,o)=>{const i=hn[e].puzzle.info;if(n<0)return!1;if(((e,t,n)=>{const o=In(e,t),i=In(e,n);return!(!o||o!==i)})(e,t,n))return!1;const l=_n(e,t),a=dn.pointAdd(_n(e,n),{x:o[0]*i.tileSize,y:o[1]*i.tileSize});if(dn.pointDistance(l,a){const o=hn[e].puzzle.tiles,i=In(e,t),l=In(e,n);let a;const c=[];i&&c.push(i),l&&c.push(l),i?a=i:l?a=l:(zn(e,{maxGroup:Mn(e)+1}),s(),a=Mn(e));if(Sn(e,t,{group:a}),r(t),Sn(e,n,{group:a}),r(n),c.length>0)for(const s of o){const t=Be.decodePiece(s);c.includes(t.group)&&(Sn(e,t.idx,{group:a}),r(t.idx))}})(e,t,n),i=Ln(e,t);const d=((e,t)=>{let n=0;for(const o of t){const t=En(e,o);t>n&&(n=t)}return n})(e,i);return Rn(e,i,d),c(i),!0}return!1};let i=!1;for(const t of Ln(e,g)){const o=$n(e,t);if(n(e,t,o[0],[0,1])||n(e,t,o[1],[-1,0])||n(e,t,o[2],[0,-1])||n(e,t,o[3],[1,0])){i=!0;break}}if(i&&xn(e)===fe.ANY){const n=Wn(e,t)+1;An(e,t,{d:u,ts:o,points:n}),d()}else An(e,t,{d:u,ts:o}),d()}}else An(e,t,{d:u,ts:o}),d();l._last_mouse=a}else if(u===pt){const i=n[1],a=n[2];An(e,t,{x:i,y:a,ts:o}),d(),l._last_mouse={x:i,y:a}}else if(u===ht){const i=n[1],a=n[2];An(e,t,{x:i,y:a,ts:o}),d(),l._last_mouse={x:i,y:a}}else An(e,t,{ts:o}),d();return function(e,t,n){hn[e].evtInfos[t]=n}(e,t,l),a}};let Yn=-10,Kn=20,Zn=2,Jn=15;class Xn{constructor(e){this.radius=10,this.previousRadius=10,this.explodingDuration=100,this.hasExploded=!1,this.alive=!0,this.color=function(e){return"rgba("+e.random(0,255)+","+e.random(0,255)+","+e.random(0,255)+", 0.8)"}(e),this.px=window.innerWidth/4+Math.random()*window.innerWidth/2,this.py=window.innerHeight,this.vx=Yn+Math.random()*Kn,this.vy=-1*(Zn+Math.random()*Jn),this.duration=0}update(e){if(this.hasExploded){const e=200-this.radius;this.previousRadius=this.radius,this.radius+=e/10,this.explodingDuration--,0==this.explodingDuration&&(this.alive=!1)}else this.vx+=0,this.vy+=1,this.vy>=0&&e&&this.explode(e),this.px+=this.vx,this.py+=this.vy}draw(e){e.beginPath(),e.arc(this.px,this.py,this.previousRadius,0,2*Math.PI,!1),this.hasExploded||(e.fillStyle=this.color,e.lineWidth=1,e.fill())}explode(e){this.hasExploded=!0;const t=3+Math.floor(3*Math.random());for(let n=0;n{this.resize()}))}setSpeedParams(){let e=0,t=0;for(;e=0;)t+=1,e+=t;Zn=t/2,Jn=t-Zn;const n=1/4*this.canvas.width/(t/2);Yn=-n,Kn=2*n}resize(){this.setSpeedParams()}init(){this.readyBombs=[],this.explodedBombs=[],this.particles=[];for(let e=0;e<1;e++)this.readyBombs.push(new Xn(this.rng))}update(){100*Math.random()<5&&this.readyBombs.push(new Xn(this.rng));const e=[];for(;this.explodedBombs.length>0;){const t=this.explodedBombs.shift();if(!t)break;t.update(),t.alive&&e.push(t)}this.explodedBombs=e;const t=[];for(;this.readyBombs.length>0;){const e=this.readyBombs.shift();if(!e)break;e.update(this.particles),e.hasExploded?this.explodedBombs.push(e):t.push(e)}this.readyBombs=t;const n=[];for(;this.particles.length>0;){const e=this.particles.shift();if(!e)break;e.update(),e.alive&&n.push(e)}this.particles=n}render(){this.ctx.beginPath(),this.ctx.fillStyle="rgba(0, 0, 0, 0.1)",this.ctx.fillRect(0,0,this.canvas.width,this.canvas.height);for(let e=0;e{const t=e.color+" "+e.d;if(!h[t]){const n=e.d?a:s;if(e.color){const o=e.d?r:c;h[t]=await createImageBitmap(tn.colorizedCanvas(n,o,e.color))}else h[t]=n}return h[t]},y=function(e,t){return t.width=window.innerWidth,t.height=window.innerHeight,e.appendChild(t),window.addEventListener("resize",(()=>{t.width=window.innerWidth,t.height=window.innerHeight,lo=!0})),t}(i,tn.createCanvas()),f={final:!1,requesting:!0,log:[],logPointer:0,speeds:[.5,1,2,5,10,20,50,100,250,500],speedIdx:1,paused:!1,lastRealTs:0,lastGameTs:0,gameStartTs:0,dataOffset:0,dataSize:1e4};Dt.onConnectionStateChange((e=>{l.setConnectionState(e)}));const w=async e=>{f.requesting=!0;const t=await Dt.requestReplayData(e,f.dataOffset,f.dataSize);return f.dataOffset+=f.dataSize,f.requesting=!1,t};let v=()=>0;const b=async()=>{if("play"===o){const o=await Dt.connect(n,e,t),i=Be.decodeGame(o);Qn.setGame(i.id,i),v=()=>D()}else{if("replay"!==o)throw"[ 2020-12-22 MODE invalid, must be play|replay ]";{const t=await w(e);if(!t.game)throw"[ 2021-05-29 no game received ]";const n=Be.decodeGame(t.game);Qn.setGame(n.id,n),f.requesting=!1,f.log=t.log,f.lastRealTs=D(),f.gameStartTs=parseInt(f.log[0][4],10),f.lastGameTs=f.gameStartTs,v=()=>f.lastGameTs}}lo=!0};await b();const x=Qn.getPieceDrawOffset(e),C=Qn.getPieceDrawSize(e),k=Qn.getPuzzleWidth(e),A=Qn.getPuzzleHeight(e),z=Qn.getTableWidth(e),S=Qn.getTableHeight(e),P={x:(z-k)/2,y:(S-A)/2},I={w:k,h:A},T={w:C,h:C},_=await pn.loadPuzzleBitmaps(Qn.getPuzzle(e)),B=new to(y,Qn.getRng(e));B.init();const E=y.getContext("2d");y.classList.add("loaded");const O=Xt();O.move(-(z-y.width)/2,-(S-y.height)/2);const N=function(e,t,n){let o=[],i=!0,l=!1,a=!1,s=!1,r=!1,c=!1,d=!1,u=!1;const g=(e,t)=>{const o=n.viewportToWorld({x:e,y:t});return[o.x,o.y]},p=e=>g(e.offsetX,e.offsetY),h=()=>g(e.width/2,e.height/2),m=(e,t)=>{i&&("Shift"===t.key?u=e:"ArrowUp"===t.key||"w"===t.key||"W"===t.key?s=e:"ArrowDown"===t.key||"s"===t.key||"S"===t.key?r=e:"ArrowLeft"===t.key||"a"===t.key||"A"===t.key?l=e:"ArrowRight"===t.key||"d"===t.key||"D"===t.key?a=e:"q"===t.key?d=e:"e"===t.key&&(c=e))};e.addEventListener("mousedown",(e=>{0===e.button&&y([dt,...p(e)])})),e.addEventListener("mouseup",(e=>{0===e.button&&y([ut,...p(e)])})),e.addEventListener("mousemove",(e=>{y([gt,...p(e)])})),e.addEventListener("wheel",(e=>{if(n.canZoom(e.deltaY<0?"in":"out")){const t=e.deltaY<0?pt:ht;y([t,...p(e)])}})),t.addEventListener("keydown",(e=>m(!0,e))),t.addEventListener("keyup",(e=>m(!1,e))),t.addEventListener("keypress",(e=>{i&&(" "===e.key&&y([wt]),"F"!==e.key&&"f"!==e.key||(oo=!oo,lo=!0),"G"!==e.key&&"g"!==e.key||(io=!io,lo=!0))}));const y=e=>{o.push(e)};return{addEvent:y,consumeAll:()=>{if(0===o.length)return[];const e=o.slice();return o=[],e},createKeyEvents:()=>{const e=u?20:10,t=(l?e:0)-(a?e:0),o=(s?e:0)-(r?e:0);0===t&&0===o||y([ct,t,o]),c&&d||(c?n.canZoom("in")&&y([pt,...h()]):d&&n.canZoom("out")&&y([ht,...h()]))},setHotkeys:e=>{i=e}}}(y,window,O),U=Qn.getImageUrl(e),M=()=>{const t=Qn.getStartTs(e),n=Qn.getFinishTs(e),o=v();l.setFinished(!!n),l.setDuration((n||o)-t)};M(),l.setPiecesDone(Qn.getFinishedPiecesCount(e)),l.setPiecesTotal(Qn.getPieceCount(e));const G=v();l.setActivePlayers(Qn.getActivePlayers(e,G)),l.setIdlePlayers(Qn.getIdlePlayers(e,G));const $=!!Qn.getFinishTs(e);let R=$;const V=()=>R&&!$,j=()=>Qn.getPlayerBgColor(e,t)||localStorage.getItem("bg_color")||"#222222",F=()=>Qn.getPlayerColor(e,t)||localStorage.getItem("player_color")||"#ffffff";let L="",W="",q=!1;const H=e=>{q=e;const[t,n]=e?[L,"grab"]:[W,"default"];y.style.cursor=`url('${t}') ${u} ${p}, ${n}`},Q=e=>{L=tn.colorizedCanvas(a,r,e).toDataURL(),W=tn.colorizedCanvas(s,c,e).toDataURL(),H(q)};Q(F());const Y=()=>{l.setReplaySpeed&&l.setReplaySpeed(f.speeds[f.speedIdx]),l.setReplayPaused&&l.setReplayPaused(f.paused)};if("play"===o?setInterval(M,1e3):"replay"===o&&Y(),"play"===o)Dt.onServerChange((n=>{n[0],n[1],n[2];const o=n[3];for(const[i,l]of o)switch(i){case xt:{const n=Be.decodePlayer(l);n.id!==t&&(Qn.setPlayer(e,n.id,n),lo=!0)}break;case bt:{const t=Be.decodePiece(l);Qn.setPiece(e,t.idx,t),lo=!0}break;case vt:Qn.setPuzzleData(e,l),lo=!0}R=!!Qn.getFinishTs(e)}));else if("replay"===o){const t=setInterval((()=>{const n=D();if(f.requesting)return void(f.lastRealTs=n);if(f.logPointer+1>=f.log.length)return f.lastRealTs=n,void(async e=>{const t=await w(e);f.log=f.log.slice(f.logPointer),f.logPointer=0,f.log.push(...t.log),t.log.length=f.log.length){f.final&&clearInterval(t);break}const o=f.log[n],l=f.gameStartTs+o[o.length-1];if(l>i)break;const a=o.slice();if(a[0]===at){const t=a[1];Qn.addPlayer(e,t,l),lo=!0}else if(a[0]===st){const t=Qn.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (update player) ]";Qn.addPlayer(e,t,l),lo=!0}else if(a[0]===rt){const t=Qn.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (handle input) ]";const n=a[2];Qn.handleInput(e,t,n,l),lo=!0}f.logPointer=n}f.lastRealTs=n,f.lastGameTs=i,M()}),50)}let K=null;return(e=>{const t=e.fps||60,n=e.slow||1,o=e.update,i=e.render,l=window.requestAnimationFrame,a=1/t,s=n*a;let r,c=0,d=window.performance.now();const u=()=>{for(r=window.performance.now(),c+=Math.min(1,(r-d)/1e3);c>s;)c-=s,o(a);i(c/n),d=r,l(u)};l(u)})({update:()=>{N.createKeyEvents();for(const n of N.consumeAll())if("play"===o){const o=n[0];if(o===ct){const e=n[1],t=n[2];lo=!0,O.move(e,t)}else if(o===gt){if(K&&!Qn.getFirstOwnedPiece(e,t)){const e={x:n[1],y:n[2]},t=O.worldToViewport(e),o=Math.round(t.x-K.x),i=Math.round(t.y-K.y);lo=!0,O.move(o,i),K=t}}else if(o===yt)Q(n[1]);else if(o===dt){const e={x:n[1],y:n[2]};K=O.worldToViewport(e),H(!0)}else if(o===ut)K=null,H(!1);else if(o===pt){const e={x:n[1],y:n[2]};lo=!0,O.zoom("in",O.worldToViewport(e))}else if(o===ht){const e={x:n[1],y:n[2]};lo=!0,O.zoom("out",O.worldToViewport(e))}else o===wt&&l.togglePreview();const i=v();Qn.handleInput(e,t,n,i).length>0&&(lo=!0),Dt.sendClientEvent(n)}else if("replay"===o){const e=n[0];if(e===ct){const e=n[1],t=n[2];lo=!0,O.move(e,t)}else if(e===gt){if(K){const e={x:n[1],y:n[2]},t=O.worldToViewport(e),o=Math.round(t.x-K.x),i=Math.round(t.y-K.y);lo=!0,O.move(o,i),K=t}}else if(e===dt){const e={x:n[1],y:n[2]};K=O.worldToViewport(e)}else if(e===ut)K=null;else if(e===pt){const e={x:n[1],y:n[2]};lo=!0,O.zoom("in",O.worldToViewport(e))}else if(e===ht){const e={x:n[1],y:n[2]};lo=!0,O.zoom("out",O.worldToViewport(e))}else e===wt&&l.togglePreview()}R=!!Qn.getFinishTs(e),V()&&(B.update(),lo=!0)},render:async()=>{if(!lo)return;const n=v();let i,a,s;window.DEBUG&&an(0),E.fillStyle=j(),E.fillRect(0,0,y.width,y.height),window.DEBUG&&sn("clear done"),i=O.worldToViewportRaw(P),a=O.worldDimToViewportRaw(I),E.fillStyle="rgba(255, 255, 255, .3)",E.fillRect(i.x,i.y,a.w,a.h),window.DEBUG&&sn("board done");const r=Qn.getPiecesSortedByZIndex(e);window.DEBUG&&sn("get tiles done"),a=O.worldDimToViewportRaw(T);for(const e of r)(-1===e.owner?oo:io)&&(s=_[e.idx],i=O.worldToViewportRaw({x:x+e.pos.x,y:x+e.pos.y}),E.drawImage(s,0,0,s.width,s.height,i.x,i.y,a.w,a.h));window.DEBUG&&sn("tiles done");const c=[];for(const l of Qn.getActivePlayers(e,n))d=l,("replay"===o||d.id!==t)&&(s=await m(l),i=O.worldToViewport(l),E.drawImage(s,i.x-u,i.y-p),c.push([`${l.name} (${l.points})`,i.x,i.y+g]));var d;E.fillStyle="white",E.textAlign="center";for(const[e,t,o]of c)E.fillText(e,t,o);window.DEBUG&&sn("players done"),l.setActivePlayers(Qn.getActivePlayers(e,n)),l.setIdlePlayers(Qn.getIdlePlayers(e,n)),l.setPiecesDone(Qn.getFinishedPiecesCount(e)),window.DEBUG&&sn("HUD done"),V()&&B.render(),lo=!1}}),{setHotkeys:e=>{N.setHotkeys(e)},onBgChange:e=>{localStorage.setItem("bg_color",e),N.addEvent([mt,e])},onColorChange:e=>{localStorage.setItem("player_color",e),N.addEvent([yt,e])},onNameChange:e=>{localStorage.setItem("player_name",e),N.addEvent([ft,e])},replayOnSpeedUp:()=>{f.speedIdx+1{f.speedIdx>=1&&(f.speedIdx--,Y())},replayOnPauseToggle:()=>{f.paused=!f.paused,Y()},previewImageUrl:U,player:{background:j(),color:F(),name:Qn.getPlayerName(e,t)||localStorage.getItem("player_name")||"anon"},disconnect:Dt.disconnect,connect:b}}var so=e({name:"game",components:{PuzzleStatus:Qe,Scores:Fe,SettingsOverlay:Ke,PreviewOverlay:et,ConnectionOverlay:Bt,HelpOverlay:Gt},data:()=>({activePlayers:[],idlePlayers:[],finished:!1,duration:0,piecesDone:0,piecesTotal:0,overlay:"",connectionState:0,g:{player:{background:"",color:"",name:""},previewImageUrl:"",setHotkeys:e=>{},onBgChange:e=>{},onColorChange:e=>{},onNameChange:e=>{},disconnect:()=>{},connect:()=>{}}}),async mounted(){this.$route.params.id&&(this.$watch((()=>this.g.player.background),(e=>{this.g.onBgChange(e)})),this.$watch((()=>this.g.player.color),(e=>{this.g.onColorChange(e)})),this.$watch((()=>this.g.player.name),(e=>{this.g.onNameChange(e)})),this.g=await ao(`${this.$route.params.id}`,this.$clientId,this.$config.WS_ADDRESS,"play",this.$el,{setActivePlayers:e=>{this.activePlayers=e},setIdlePlayers:e=>{this.idlePlayers=e},setFinished:e=>{this.finished=e},setDuration:e=>{this.duration=e},setPiecesDone:e=>{this.piecesDone=e},setPiecesTotal:e=>{this.piecesTotal=e},setConnectionState:e=>{this.connectionState=e},togglePreview:()=>{this.toggle("preview",!1)}}))},unmounted(){this.g.disconnect()},methods:{reconnect(){this.g.connect()},toggle(e,t){""===this.overlay?(this.overlay=e,t&&this.g.setHotkeys(!1)):(this.overlay="",t&&this.g.setHotkeys(!0))}}});const ro={id:"game"},co={class:"menu"},uo={class:"tabs"},go=s("🧩 Puzzles");so.render=function(e,i,s,r,c,d){const u=l("settings-overlay"),p=l("preview-overlay"),h=l("help-overlay"),m=l("connection-overlay"),y=l("puzzle-status"),f=l("router-link"),w=l("scores");return a(),t("div",ro,[g(n(u,{onBgclick:i[1]||(i[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":i[2]||(i[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[v,"settings"===e.overlay]]),g(n(p,{onBgclick:i[3]||(i[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[v,"preview"===e.overlay]]),g(n(h,{onBgclick:i[4]||(i[4]=t=>e.toggle("help",!0))},null,512),[[v,"help"===e.overlay]]),n(m,{connectionState:e.connectionState,onReconnect:e.reconnect},null,8,["connectionState","onReconnect"]),n(y,{finished:e.finished,duration:e.duration,piecesDone:e.piecesDone,piecesTotal:e.piecesTotal},null,8,["finished","duration","piecesDone","piecesTotal"]),n("div",co,[n("div",uo,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[go])),_:1}),n("div",{class:"opener",onClick:i[5]||(i[5]=t=>e.toggle("preview",!1))},"đŸ–ŧī¸ Preview"),n("div",{class:"opener",onClick:i[6]||(i[6]=t=>e.toggle("settings",!0))},"đŸ› ī¸ Settings"),n("div",{class:"opener",onClick:i[7]||(i[7]=t=>e.toggle("help",!0))},"â„šī¸ Help")])]),n(w,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])};var po=e({name:"replay",components:{PuzzleStatus:Qe,Scores:Fe,SettingsOverlay:Ke,PreviewOverlay:et,HelpOverlay:Gt},data:()=>({activePlayers:[],idlePlayers:[],finished:!1,duration:0,piecesDone:0,piecesTotal:0,overlay:"",connectionState:0,g:{player:{background:"",color:"",name:""},previewImageUrl:"",setHotkeys:e=>{},onBgChange:e=>{},onColorChange:e=>{},onNameChange:e=>{},replayOnSpeedUp:()=>{},replayOnSpeedDown:()=>{},replayOnPauseToggle:()=>{},disconnect:()=>{}},replay:{speed:1,paused:!1}}),async mounted(){this.$route.params.id&&(this.$watch((()=>this.g.player.background),(e=>{this.g.onBgChange(e)})),this.$watch((()=>this.g.player.color),(e=>{this.g.onColorChange(e)})),this.$watch((()=>this.g.player.name),(e=>{this.g.onNameChange(e)})),this.g=await ao(`${this.$route.params.id}`,this.$clientId,this.$config.WS_ADDRESS,"replay",this.$el,{setActivePlayers:e=>{this.activePlayers=e},setIdlePlayers:e=>{this.idlePlayers=e},setFinished:e=>{this.finished=e},setDuration:e=>{this.duration=e},setPiecesDone:e=>{this.piecesDone=e},setPiecesTotal:e=>{this.piecesTotal=e},togglePreview:()=>{this.toggle("preview",!1)},setConnectionState:e=>{this.connectionState=e},setReplaySpeed:e=>{this.replay.speed=e},setReplayPaused:e=>{this.replay.paused=e}}))},unmounted(){this.g.disconnect()},methods:{toggle(e,t){""===this.overlay?(this.overlay=e,t&&this.g.setHotkeys(!1)):(this.overlay="",t&&this.g.setHotkeys(!0))}},computed:{replayText(){return"Replay-Speed: "+this.replay.speed+"x"+(this.replay.paused?" Paused":"")}}});const ho={id:"replay"},mo={class:"menu"},yo={class:"tabs"},fo=s("🧩 Puzzles");po.render=function(e,i,s,c,d,u){const p=l("settings-overlay"),h=l("preview-overlay"),m=l("help-overlay"),y=l("puzzle-status"),f=l("router-link"),w=l("scores");return a(),t("div",ho,[g(n(p,{onBgclick:i[1]||(i[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":i[2]||(i[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[v,"settings"===e.overlay]]),g(n(h,{onBgclick:i[3]||(i[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[v,"preview"===e.overlay]]),g(n(m,{onBgclick:i[4]||(i[4]=t=>e.toggle("help",!0))},null,512),[[v,"help"===e.overlay]]),n(y,{finished:e.finished,duration:e.duration,piecesDone:e.piecesDone,piecesTotal:e.piecesTotal},{default:o((()=>[n("div",null,[n("div",null,r(e.replayText),1),n("button",{class:"btn",onClick:i[5]||(i[5]=t=>e.g.replayOnSpeedUp())},"âĢ"),n("button",{class:"btn",onClick:i[6]||(i[6]=t=>e.g.replayOnSpeedDown())},"âŦ"),n("button",{class:"btn",onClick:i[7]||(i[7]=t=>e.g.replayOnPauseToggle())},"â¸ī¸")])])),_:1},8,["finished","duration","piecesDone","piecesTotal"]),n("div",mo,[n("div",yo,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[fo])),_:1}),n("div",{class:"opener",onClick:i[8]||(i[8]=t=>e.toggle("preview",!1))},"đŸ–ŧī¸ Preview"),n("div",{class:"opener",onClick:i[9]||(i[9]=t=>e.toggle("settings",!0))},"đŸ› ī¸ Settings"),n("div",{class:"opener",onClick:i[10]||(i[10]=t=>e.toggle("help",!0))},"â„šī¸ Help")])]),n(w,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])},(async()=>{const e=await fetch("/api/conf"),t=await e.json();const n=b({history:x(),routes:[{name:"index",path:"/",component:R},{name:"new-game",path:"/new-game",component:Ee},{name:"game",path:"/g/:id",component:so},{name:"replay",path:"/replay/:id",component:po}]});n.beforeEach(((e,t)=>{t.name&&document.documentElement.classList.remove(`view-${String(t.name)}`),document.documentElement.classList.add(`view-${String(e.name)}`)}));const o=C(k);o.config.globalProperties.$config=t,o.config.globalProperties.$clientId=function(){let e=localStorage.getItem("ID");return e||(e=Be.uniqId(),localStorage.setItem("ID",e)),e}(),o.use(n),o.mount("#app")})();