puzzle/build/public/assets/index.99efb0e9.js
2021-06-06 16:12:20 +02:00

1 line
61 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import{d as e,c as t,a as n,w as l,b as o,r as a,o as i,e as s,t as r,F as d,f as c,g as u,h as p,v as g,i as h,j as m,p as y,k as f,l as v,m as w,n as b,q as k,s as x,u as C,x as A,y as S}from"./vendor.684f7bc8.js";var T=e({name:"app",computed:{showNav(){return!["game","replay"].includes(String(this.$route.name))}}});const P={id:"app"},z={key:0,class:"nav"},I=s("Index"),D=s("New game");T.render=function(e,s,r,d,c,u){const p=a("router-link"),g=a("router-view");return i(),t("div",P,[e.showNav?(i(),t("ul",z,[n("li",null,[n(p,{class:"btn",to:{name:"index"}},{default:l((()=>[I])),_:1})]),n("li",null,[n(p,{class:"btn",to:{name:"new-game"}},{default:l((()=>[D])),_:1})])])):o("",!0),n(g)])};const E=864e5,_=e=>{const t=Math.floor(e/E);e%=E;const n=Math.floor(e/36e5);e%=36e5;const l=Math.floor(e/6e4);e%=6e4;return`${t}d ${n}h ${l}m ${Math.floor(e/1e3)}s`};var M=1,N=1e3,O=()=>{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-e),U=_,R=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?"🏁":"⏳",l=e,o=t||O();return`${n} ${B(l,o)}`}}});const V={class:"game-info-text"},G=n("br",null,null,-1),$=n("br",null,null,-1),F=n("br",null,null,-1),L=s(" ↪️ Watch replay ");R.render=function(e,d,c,u,p,g){const h=a("router-link");return i(),t("div",{class:"game-teaser",style:e.style},[n(h,{class:"game-info",to:{name:"game",params:{id:e.game.id}}},{default:l((()=>[n("span",V,[s(" 🧩 "+r(e.game.tilesFinished)+"/"+r(e.game.tilesTotal),1),G,s(" 👥 "+r(e.game.players),1),$,s(" "+r(e.time(e.game.started,e.game.finished)),1),F])])),_:1},8,["to"]),e.game.hasReplay?(i(),t(h,{key:0,class:"game-replay",to:{name:"replay",params:{id:e.game.id}}},{default:l((()=>[L])),_:1},8,["to"])):o("",!0)],4)};var j=e({components:{GameTeaser:R},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 W=n("h1",null,"Running games",-1),H=n("h1",null,"Finished games",-1);j.render=function(e,l,o,s,r,u){const p=a("game-teaser");return i(),t("div",null,[W,(i(!0),t(d,null,c(e.gamesRunning,((e,l)=>(i(),t("div",{class:"game-teaser-wrap",key:l},[n(p,{game:e},null,8,["game"])])))),128)),H,(i(!0),t(d,null,c(e.gamesFinished,((e,l)=>(i(),t("div",{class:"game-teaser-wrap",key:l},[n(p,{game:e},null,8,["game"])])))),128))])};var Y=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")}}});Y.render=function(e,l,o,a,s,r){return i(),t("div",{class:"imageteaser",style:e.style,onClick:l[2]||(l[2]=(...t)=>e.onClick&&e.onClick(...t))},[n("div",{class:"btn edit",onClick:l[1]||(l[1]=u(((...t)=>e.onEditClick&&e.onEditClick(...t)),["stop"]))},"✏️")],4)};var Q,q,Z,K,X,J,ee,te,ne=e({name:"image-library",components:{ImageTeaser:Y},props:{images:{type:Array,required:!0}},emits:{imageClicked:null,imageEditClicked:null},methods:{imageClicked(e){this.$emit("imageClicked",e)},imageEditClicked(e){this.$emit("imageEditClicked",e)}}});ne.render=function(e,n,l,o,s,r){const u=a("image-teaser");return i(),t("div",null,[(i(!0),t(d,null,c(e.images,((n,l)=>(i(),t(u,{image:n,onClick:t=>e.imageClicked(n),onEditClick:t=>e.imageEditClicked(n),key:l},null,8,["image","onClick","onEditClick"])))),128))])},(q=Q||(Q={}))[q.Flat=0]="Flat",q[q.Out=1]="Out",q[q.In=-1]="In",(K=Z||(Z={}))[K.FINAL=0]="FINAL",K[K.ANY=1]="ANY",(J=X||(X={}))[J.NORMAL=0]="NORMAL",J[J.ANY=1]="ANY",J[J.FLAT=2]="FLAT",(te=ee||(ee={}))[te.NORMAL=0]="NORMAL",te[te.REAL=1]="REAL";class le{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),l=t[n];t[n]=t[e],t[e]=l}return t}static serialize(e){return{rand_high:e.rand_high,rand_low:e.rand_low}}static unserialize(e){const t=new le(0);return t.rand_high=e.rand_high,t.rand_low=e.rand_low,t}}const oe=(e,t)=>{const n=`${e}`;return n.length>=t.length?n:t.substr(0,t.length-n.length)+n},ae=(...e)=>{const t=t=>(...n)=>{const l=new Date,o=oe(l.getHours(),"00"),a=oe(l.getMinutes(),"00"),i=oe(l.getSeconds(),"00");console[t](`${o}:${a}:${i}`,...e,...n)};return{log:t("log"),error:t("error"),info:t("info")}};var ie={hash:e=>{let t=0;for(let n=0;n<e.length;n++){t=(t<<5)-t+e.charCodeAt(n),t|=0}return t},slug:e=>{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||"",le.serialize(e.rng.obj),e.puzzle,e.players,e.evtInfos,e.scoreMode||Z.FINAL,e.shapeMode||X.ANY,e.snapMode||ee.NORMAL]},decodeGame:function(e){return{id:e[0],rng:{type:e[1],obj:le.unserialize(e[2])},puzzle:e[3],players:e[4],evtInfos:e[5],scoreMode:e[6],shapeMode:e[7],snapMode:e[8]}},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 l=[n,e[n]].map(encodeURIComponent);t.push(l.join("="))}return 0===t.length?"":`?${t.join("&")}`}};const se={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}}}};se.render=function(e,n,l,o,a,s){return i(),t("div",{style:s.style,title:l.title},null,12,["title"])};var re=e({name:"tags-input",props:{modelValue:{type:Array,required:!0},autocompleteTags:{type:Function}},emits:{"update:modelValue":null},data:()=>({input:"",values:[],autocomplete:{idx:-1,values:[]}}),created(){this.values=this.modelValue},methods:{onKeyUp(e){return"ArrowDown"===e.key&&this.autocomplete.values.length>0?(this.autocomplete.idx<this.autocomplete.values.length-1&&this.autocomplete.idx++,e.stopPropagation(),!1):"ArrowUp"===e.key&&this.autocomplete.values.length>0?(this.autocomplete.idx>0&&this.autocomplete.idx--,e.stopPropagation(),!1):","===e.key?(this.add(),e.stopPropagation(),!1):void(this.input&&this.autocompleteTags?(this.autocomplete.values=this.autocompleteTags(this.input,this.values),this.autocomplete.idx=-1):(this.autocomplete.values=[],this.autocomplete.idx=-1))},addVal(e){const t=e.replace(/,/g,"").trim();t&&(this.values.includes(t)||this.values.push(t),this.input="",this.autocomplete.values=[],this.autocomplete.idx=-1,this.$emit("update:modelValue",this.values),this.$refs.input.focus())},add(){const e=this.autocomplete.idx>=0?this.autocomplete.values[this.autocomplete.idx]:this.input;this.addVal(e)},rm(e){this.values=this.values.filter((t=>t!==e)),this.$emit("update:modelValue",this.values)}}});const de=m();y("data-v-39ed99c7");const ce={key:0,class:"autocomplete"};f();const ue=de(((e,l,a,s,u,m)=>(i(),t("div",null,[p(n("input",{ref:"input",class:"input",type:"text","onUpdate:modelValue":l[1]||(l[1]=t=>e.input=t),placeholder:"Plants, People",onChange:l[2]||(l[2]=(...t)=>e.onChange&&e.onChange(...t)),onKeydown:l[3]||(l[3]=h(((...t)=>e.add&&e.add(...t)),["enter"])),onKeyup:l[4]||(l[4]=(...t)=>e.onKeyUp&&e.onKeyUp(...t))},null,544),[[g,e.input]]),e.autocomplete.values?(i(),t("div",ce,[n("ul",null,[(i(!0),t(d,null,c(e.autocomplete.values,((n,l)=>(i(),t("li",{key:l,class:{active:l===e.autocomplete.idx},onClick:t=>e.addVal(n)},r(n),11,["onClick"])))),128))])])):o("",!0),(i(!0),t(d,null,c(e.values,((n,l)=>(i(),t("span",{key:l,class:"bit",onClick:t=>e.rm(n)},r(n)+" ✖",9,["onClick"])))),128))]))));re.render=ue,re.__scopeId="data-v-39ed99c7";const pe=ae("NewImageDialog.vue");var ge=e({name:"new-image-dialog",components:{ResponsiveImage:se,TagsInput:re},props:{autocompleteTags:{type:Function}},emits:{bgclick:null,setupGameClick:null,postToGalleryClick:null},data:()=>({previewUrl:"",file:null,title:"",tags:[],droppable:!1}),computed:{canPostToGallery(){return!(!this.previewUrl||!this.file)},canSetupGameClick(){return!(!this.previewUrl||!this.file)}},methods:{imageFromDragEvt(e){var t;const n=null==(t=e.dataTransfer)?void 0:t.items;if(!n||0===n.length)return null;const l=n[0];return l.type.startsWith("image/")?l:null},onFileSelect(e){const t=e.target;if(!t.files)return;const n=t.files[0];n&&this.preview(n)},preview(e){const t=new FileReader;t.readAsDataURL(e),t.onload=t=>{this.previewUrl=t.target.result,this.file=e}},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})},onDrop(e){this.droppable=!1;const t=this.imageFromDragEvt(e);if(!t)return!1;const n=t.getAsFile();return!!n&&(this.file=n,this.preview(n),e.preventDefault(),!1)},onDragover(e){return!!this.imageFromDragEvt(e)&&(this.droppable=!0,e.preventDefault(),!1)},onDragleave(){pe.info("onDragleave"),this.droppable=!1}}});const he=n("div",{class:"drop-target"},null,-1),me={key:0,class:"has-image"},ye={key:1},fe={class:"upload"},ve=n("span",{class:"btn"},"Upload File",-1),we={class:"area-settings"},be=n("td",null,[n("label",null,"Title")],-1),ke=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),xe=n("td",null,[n("label",null,"Tags")],-1),Ce={class:"area-buttons"},Ae=s("🧩 Post to gallery "),Se=n("br",null,null,-1),Te=s(" + set up game");ge.render=function(e,l,o,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),t("div",{class:"overlay new-image-dialog",onClick:l[11]||(l[11]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:l[10]||(l[10]=u((()=>{}),["stop"]))},[n("div",{class:["area-image",{"has-image":!!e.previewUrl,"no-image":!e.previewUrl,droppable:e.droppable}],onDrop:l[3]||(l[3]=(...t)=>e.onDrop&&e.onDrop(...t)),onDragover:l[4]||(l[4]=(...t)=>e.onDragover&&e.onDragover(...t)),onDragleave:l[5]||(l[5]=(...t)=>e.onDragleave&&e.onDragleave(...t))},[he,e.previewUrl?(i(),t("div",me,[n("span",{class:"remove btn",onClick:l[1]||(l[1]=t=>e.previewUrl="")},"X"),n(c,{src:e.previewUrl},null,8,["src"])])):(i(),t("div",ye,[n("label",fe,[n("input",{type:"file",style:{display:"none"},onChange:l[2]||(l[2]=(...t)=>e.onFileSelect&&e.onFileSelect(...t)),accept:"image/*"},null,32),ve])]))],34),n("div",we,[n("table",null,[n("tr",null,[be,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":l[6]||(l[6]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),ke,n("tr",null,[xe,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":l[7]||(l[7]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",Ce,[n("button",{class:"btn",disabled:!e.canPostToGallery,onClick:l[8]||(l[8]=(...t)=>e.postToGallery&&e.postToGallery(...t))},"🖼️ Post to gallery",8,["disabled"]),n("button",{class:"btn",disabled:!e.canSetupGameClick,onClick:l[9]||(l[9]=(...t)=>e.setupGameClick&&e.setupGameClick(...t))},[Ae,Se,Te],8,["disabled"])])])])};var Pe=e({name:"edit-image-dialog",components:{ResponsiveImage:se,TagsInput:re},props:{image:{type:Object,required:!0},autocompleteTags:{type:Function}},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 ze={class:"area-image"},Ie={class:"has-image"},De={class:"area-settings"},Ee=n("td",null,[n("label",null,"Title")],-1),_e=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),Me=n("td",null,[n("label",null,"Tags")],-1),Ne={class:"area-buttons"};Pe.render=function(e,l,o,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),t("div",{class:"overlay edit-image-dialog",onClick:l[5]||(l[5]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:l[4]||(l[4]=u((()=>{}),["stop"]))},[n("div",ze,[n("div",Ie,[n(c,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",De,[n("table",null,[n("tr",null,[Ee,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":l[1]||(l[1]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),_e,n("tr",null,[Me,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":l[2]||(l[2]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",Ne,[n("button",{class:"btn",onClick:l[3]||(l[3]=(...t)=>e.saveImage&&e.saveImage(...t))},"🖼️ Save image")])])])};var Oe=e({name:"new-game-dialog",components:{ResponsiveImage:se},props:{image:{type:Object,required:!0}},emits:{newGame:null,bgclick:null},data:()=>({tiles:1e3,scoreMode:Z.ANY,shapeMode:X.NORMAL,snapMode:ee.NORMAL}),methods:{onNewGameClick(){this.$emit("newGame",{tiles:this.tilesInt,image:this.image,scoreMode:this.scoreModeInt,shapeMode:this.shapeModeInt,snapMode:this.snapModeInt})}},computed:{canStartNewGame(){return!!(this.tilesInt&&this.image&&this.image.url&&[0,1].includes(this.scoreModeInt))},scoreModeInt(){return parseInt(`${this.scoreMode}`,10)},shapeModeInt(){return parseInt(`${this.shapeMode}`,10)},snapModeInt(){return parseInt(`${this.snapMode}`,10)},tilesInt(){return parseInt(`${this.tiles}`,10)}}});const Be={class:"area-image"},Ue={class:"has-image"},Re={key:0,class:"image-title"},Ve={class:"area-settings"},Ge=n("td",null,[n("label",null,"Pieces")],-1),$e=n("td",null,[n("label",null,"Scoring: ")],-1),Fe=s(" Any (Score when pieces are connected to each other or on final location)"),Le=n("br",null,null,-1),je=s(" Final (Score when pieces are put to their final location)"),We=n("td",null,[n("label",null,"Shapes: ")],-1),He=s(" Normal"),Ye=n("br",null,null,-1),Qe=s(" Any (flat pieces can occur anywhere)"),qe=n("br",null,null,-1),Ze=s(" Flat (all pieces flat on all sides)"),Ke=n("td",null,[n("label",null,"Snapping: ")],-1),Xe=s(" Normal (pieces snap to final destination and to each other)"),Je=n("br",null,null,-1),et=s(" Real (pieces snap only to corners, already snapped pieces and to each other)"),tt={class:"area-buttons"};Oe.render=function(e,l,s,d,c,h){const m=a("responsive-image");return i(),t("div",{class:"overlay new-game-dialog",onClick:l[11]||(l[11]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:l[10]||(l[10]=u((()=>{}),["stop"]))},[n("div",Be,[n("div",Ue,[n(m,{src:e.image.url,title:e.image.title},null,8,["src","title"])]),e.image.title?(i(),t("div",Re,'"'+r(e.image.title)+'"',1)):o("",!0)]),n("div",Ve,[n("table",null,[n("tr",null,[Ge,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":l[1]||(l[1]=t=>e.tiles=t)},null,512),[[g,e.tiles]])])]),n("tr",null,[$e,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[2]||(l[2]=t=>e.scoreMode=t),value:"1"},null,512),[[v,e.scoreMode]]),Fe]),Le,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[3]||(l[3]=t=>e.scoreMode=t),value:"0"},null,512),[[v,e.scoreMode]]),je])])]),n("tr",null,[We,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[4]||(l[4]=t=>e.shapeMode=t),value:"0"},null,512),[[v,e.shapeMode]]),He]),Ye,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[5]||(l[5]=t=>e.shapeMode=t),value:"1"},null,512),[[v,e.shapeMode]]),Qe]),qe,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[6]||(l[6]=t=>e.shapeMode=t),value:"2"},null,512),[[v,e.shapeMode]]),Ze])])]),n("tr",null,[Ke,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[7]||(l[7]=t=>e.snapMode=t),value:"0"},null,512),[[v,e.snapMode]]),Xe]),Je,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":l[8]||(l[8]=t=>e.snapMode=t),value:"1"},null,512),[[v,e.snapMode]]),et])])])])]),n("div",tt,[n("button",{class:"btn",disabled:!e.canStartNewGame,onClick:l[9]||(l[9]=(...t)=>e.onNewGameClick&&e.onNewGameClick(...t))}," 🧩 Generate Puzzle ",8,["disabled"])])])])};var nt=e({components:{ImageLibrary:ne,NewImageDialog:ge,EditImageDialog:Pe,NewGameDialog:Oe},data:()=>({filters:{sort:"date_desc",tags:[]},images:[],tags:[],image:{id:0,filename:"",file:"",url:"",title:"",tags:[],created:0},dialog:""}),async created(){await this.loadImages()},computed:{relevantTags(){return this.tags.filter((e=>e.total>0))}},methods:{autocompleteTags(e,t){return this.tags.filter((n=>!t.includes(n.title)&&n.title.toLowerCase().startsWith(e.toLowerCase()))).slice(0,10).map((e=>e.title))},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${ie.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("/api/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 lt={class:"upload-image-teaser"},ot=n("div",{class:"hint"},"(The image you upload will be added to the public gallery.)",-1),at={key:0},it=s(" Tags: "),st=s(" Sort by: "),rt=n("option",{value:"date_desc"},"Newest first",-1),dt=n("option",{value:"date_asc"},"Oldest first",-1),ct=n("option",{value:"alpha_asc"},"A-Z",-1),ut=n("option",{value:"alpha_desc"},"Z-A",-1);nt.render=function(e,l,s,u,g,h){const m=a("image-library"),y=a("new-image-dialog"),f=a("edit-image-dialog"),v=a("new-game-dialog");return i(),t("div",null,[n("div",lt,[n("div",{class:"btn btn-big",onClick:l[1]||(l[1]=t=>e.dialog="new-image")},"Upload your image"),ot]),n("div",null,[e.tags.length>0?(i(),t("label",at,[it,(i(!0),t(d,null,c(e.relevantTags,((n,l)=>(i(),t("span",{class:["bit",{on:e.filters.tags.includes(n.slug)}],key:l,onClick:t=>e.toggleTag(n)},r(n.title)+" ("+r(n.total)+")",11,["onClick"])))),128))])):o("",!0),n("label",null,[st,p(n("select",{"onUpdate:modelValue":l[2]||(l[2]=t=>e.filters.sort=t),onChange:l[3]||(l[3]=(...t)=>e.filtersChanged&&e.filtersChanged(...t))},[rt,dt,ct,ut],544),[[w,e.filters.sort]])])]),n(m,{images:e.images,onImageClicked:e.onImageClicked,onImageEditClicked:e.onImageEditClicked},null,8,["images","onImageClicked","onImageEditClicked"]),"new-image"===e.dialog?(i(),t(y,{key:0,autocompleteTags:e.autocompleteTags,onBgclick:l[4]||(l[4]=t=>e.dialog=""),onPostToGalleryClick:e.postToGalleryClick,onSetupGameClick:e.setupGameClick},null,8,["autocompleteTags","onPostToGalleryClick","onSetupGameClick"])):o("",!0),"edit-image"===e.dialog?(i(),t(f,{key:1,autocompleteTags:e.autocompleteTags,onBgclick:l[5]||(l[5]=t=>e.dialog=""),onSaveClick:e.onSaveImageClick,image:e.image},null,8,["autocompleteTags","onSaveClick","image"])):o("",!0),e.image&&"new-game"===e.dialog?(i(),t(v,{key:2,onBgclick:l[6]||(l[6]=t=>e.dialog=""),onNewGame:e.onNewGame,image:e.image},null,8,["onNewGame","image"])):o("",!0)])};var pt=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 gt={class:"scores"},ht=n("div",null,"Scores",-1),mt=n("td",null,"⚡",-1),yt=n("td",null,"💤",-1);pt.render=function(e,l,o,a,s,u){return i(),t("div",gt,[ht,n("table",null,[(i(!0),t(d,null,c(e.actives,((e,l)=>(i(),t("tr",{key:l,style:{color:e.color}},[mt,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128)),(i(!0),t(d,null,c(e.idles,((e,l)=>(i(),t("tr",{key:l,style:{color:e.color}},[yt,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128))])])};var ft=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 U(this.duration)}}});const vt={class:"timer"};ft.render=function(e,l,o,a,s,d){return i(),t("div",vt,[n("div",null," 🧩 "+r(e.piecesDone)+"/"+r(e.piecesTotal),1),n("div",null,r(e.icon)+" "+r(e.durationStr),1),b(e.$slots,"default")])};var wt=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 bt=n("td",null,[n("label",null,"Background: ")],-1),kt=n("td",null,[n("label",null,"Color: ")],-1),xt=n("td",null,[n("label",null,"Name: ")],-1),Ct=n("td",null,[n("label",null,"Sounds: ")],-1);wt.render=function(e,l,o,a,s,r){return i(),t("div",{class:"overlay transparent",onClick:l[6]||(l[6]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content settings",onClick:l[5]||(l[5]=u((()=>{}),["stop"]))},[n("tr",null,[bt,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":l[1]||(l[1]=t=>e.modelValue.background=t)},null,512),[[g,e.modelValue.background]])])]),n("tr",null,[kt,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":l[2]||(l[2]=t=>e.modelValue.color=t)},null,512),[[g,e.modelValue.color]])])]),n("tr",null,[xt,n("td",null,[p(n("input",{type:"text",maxLength:"16","onUpdate:modelValue":l[3]||(l[3]=t=>e.modelValue.name=t)},null,512),[[g,e.modelValue.name]])])]),n("tr",null,[Ct,n("td",null,[p(n("input",{type:"checkbox","onUpdate:modelValue":l[4]||(l[4]=t=>e.modelValue.soundsEnabled=t)},null,512),[[k,e.modelValue.soundsEnabled]])])])])])};var At=e({name:"preview-overlay",props:{img:String},emits:{bgclick:null},computed:{previewStyle(){return{backgroundImage:`url('${this.img}')`}}}});const St={class:"preview"};At.render=function(e,l,o,a,s,r){return i(),t("div",{class:"overlay",onClick:l[1]||(l[1]=t=>e.$emit("bgclick"))},[n("div",St,[n("div",{class:"img",style:e.previewStyle},null,4)])])};var Tt=1,Pt=4,zt=2,It=3,Dt=2,Et=4,_t=3,Mt=9,Nt=1,Ot=2,Bt=3,Ut=4,Rt=5,Vt=6,Gt=7,$t=8,Ft=10,Lt=11,jt=12,Wt=13,Ht=14,Yt=1,Qt=2,qt=3;const Zt=ae("Communication.js");let Kt,Xt=[],Jt=e=>{Xt.push(e)},en=[],tn=e=>{en.push(e)};let nn=0;const ln=e=>{nn!==e&&(nn=e,tn(e))};function on(e){if(2===nn)try{Kt.send(JSON.stringify(e))}catch(t){Zt.info("unable to send message.. maybe because ws is invalid?")}}let an,sn;var rn={connect:function(e,t,n){return an=0,sn={},ln(3),new Promise((l=>{Kt=new WebSocket(e,n+"|"+t),Kt.onopen=()=>{ln(2),on([It])},Kt.onmessage=e=>{const t=JSON.parse(e.data),o=t[0];if(o===Pt){const e=t[1];l(e)}else{if(o!==Tt)throw`[ 2021-05-09 invalid connect msgType ${o} ]`;{const e=t[1],l=t[2];if(e===n&&sn[l])return void delete sn[l];Jt(t)}}},Kt.onerror=()=>{throw ln(1),"[ 2021-05-15 onerror ]"},Kt.onclose=e=>{4e3===e.code||1001===e.code?ln(4):ln(1)}}))},requestReplayData:async function(e,t){const n={gameId:e,offset:t},l=await fetch(`/api/replay-data${ie.asQueryArgs(n)}`);return await l.json()},disconnect:function(){Kt&&Kt.close(4e3),an=0,sn={}},sendClientEvent:function(e){an++,sn[an]=e,on([zt,an,sn[an]])},onServerChange:function(e){Jt=e;for(const t of Xt)Jt(t);Xt=[]},onConnectionStateChange:function(e){tn=e;for(const t of en)tn(t);en=[]},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},dn=e({name:"connection-overlay",emits:{reconnect:null},props:{connectionState:Number},computed:{lostConnection(){return this.connectionState===rn.CONN_STATE_DISCONNECTED},connecting(){return this.connectionState===rn.CONN_STATE_CONNECTING},show(){return!(!this.lostConnection&&!this.connecting)}}});const cn={key:0,class:"overlay connection-lost"},un={key:0,class:"overlay-content"},pn=n("div",null,"⁉️ LOST CONNECTION ⁉️",-1),gn={key:1,class:"overlay-content"},hn=n("div",null,"Connecting...",-1);dn.render=function(e,l,a,s,r,d){return e.show?(i(),t("div",cn,[e.lostConnection?(i(),t("div",un,[pn,n("span",{class:"btn",onClick:l[1]||(l[1]=t=>e.$emit("reconnect"))},"Reconnect")])):o("",!0),e.connecting?(i(),t("div",gn,[hn])):o("",!0)])):o("",!0)};var mn=e({name:"help-overlay",emits:{bgclick:null}});const yn=n("tr",null,[n("td",null,"⬆️ Move up:"),n("td",null,[n("div",null,[n("kbd",null,"W"),s("/"),n("kbd",null,"↑"),s("/🖱️")])])],-1),fn=n("tr",null,[n("td",null,"⬇️ Move down:"),n("td",null,[n("div",null,[n("kbd",null,"S"),s("/"),n("kbd",null,"↓"),s("/🖱️")])])],-1),vn=n("tr",null,[n("td",null,"⬅️ Move left:"),n("td",null,[n("div",null,[n("kbd",null,"A"),s("/"),n("kbd",null,"←"),s("/🖱️")])])],-1),wn=n("tr",null,[n("td",null,"➡️ Move right:"),n("td",null,[n("div",null,[n("kbd",null,"D"),s("/"),n("kbd",null,"→"),s("/🖱️")])])],-1),bn=n("tr",null,[n("td"),n("td",null,[n("div",null,[s("Move faster by holding "),n("kbd",null,"Shift")])])],-1),kn=n("tr",null,[n("td",null,"🔍+ Zoom in:"),n("td",null,[n("div",null,[n("kbd",null,"E"),s("/🖱️-Wheel")])])],-1),xn=n("tr",null,[n("td",null,"🔍- Zoom out:"),n("td",null,[n("div",null,[n("kbd",null,"Q"),s("/🖱️-Wheel")])])],-1),Cn=n("tr",null,[n("td",null,"🖼️ Toggle preview:"),n("td",null,[n("div",null,[n("kbd",null,"Space")])])],-1),An=n("tr",null,[n("td",null,"🧩✔️ Toggle fixed pieces:"),n("td",null,[n("div",null,[n("kbd",null,"F")])])],-1),Sn=n("tr",null,[n("td",null,"🧩❓ Toggle loose pieces:"),n("td",null,[n("div",null,[n("kbd",null,"G")])])],-1),Tn=n("tr",null,[n("td",null,"🔉 Toggle sounds:"),n("td",null,[n("div",null,[n("kbd",null,"M")])])],-1),Pn=n("tr",null,[n("td",null,"⏫ Speed up (replay):"),n("td",null,[n("div",null,[n("kbd",null,"I")])])],-1),zn=n("tr",null,[n("td",null,"⏬ Speed down (replay):"),n("td",null,[n("div",null,[n("kbd",null,"O")])])],-1),In=n("tr",null,[n("td",null,"⏸️ Pause (replay):"),n("td",null,[n("div",null,[n("kbd",null,"P")])])],-1);mn.render=function(e,l,o,a,s,r){return i(),t("div",{class:"overlay transparent",onClick:l[2]||(l[2]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content help",onClick:l[1]||(l[1]=u((()=>{}),["stop"]))},[yn,fn,vn,wn,bn,kn,xn,Cn,An,Sn,Tn,Pn,zn,In])])};var Dn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"/assets/click.bb97cb07.mp3"}),En=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAW0lEQVQ4je1RywrAIAxLxP//5exixRWlVgZelpOKeTQFfnDypgy3eLIkSLLL8mxGPoHsU2hPAgDHBLvRX6hZZw/fwT0BtlLSONqCbWAmEIqMZOCDDlaDR3N03gOyDCn+y4DWmAAAAABJRU5ErkJggg=="}),_n=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARElEQVQ4jWNgGAU0Af+hmBCbgYGBgYERhwHEAEYGBgYGJtIdiApYyLAZBVDsAqoagC1ACQJyY4ERg0GCISh6KA4DigEAou8LC+LnIJoAAAAASUVORK5CYII="}),Mn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVQ4ja1TQQ7AIAgD///n7jCozA2Hbk00jbG1KIrcARszTugoBs49qioZj7r2kKACptkyAOCJsJuA+GzglwHjvMSSWFVaENWVASxh5eRLiq5fN/ASjI89VcP2K3hHpq1cEXNaMfnrL3TDZP2tDuoOA6MzCCXWr38AAAAASUVORK5CYII="}),Nn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAU0lEQVQ4jWNgoAH4D8X42HDARKlt5BoAd82AuQAOGLGIYQQUPv0wF5CiCQUge4EsQ5C9QI4BjMguwBYeBAElscCIy1ZivMKIwSDBEBQ9FCckigEAU3QOD7TGvY4AAAAASUVORK5CYII="});function On(){let e=0,t=0,n=1;const l=(l,o)=>{e+=l/n,t+=o/n},o=e=>{const t=n+.05*n*("in"===e?1:-1);return Math.min(Math.max(t,.1),6)},a=l=>({x:l.x/n-e,y:l.y/n-t}),i=l=>({x:(l.x+e)*n,y:(l.y+t)*n}),s=e=>({w:e.w*n,h:e.h*n}),r=e=>({w:e.w/n,h:e.h/n});return{getCurrentZoom:()=>n,move:l,canZoom:e=>n!=o(e),zoom:(e,t)=>((e,t)=>{if(n==e)return!1;const o=1-n/e;return l(-t.x*o,-t.y*o),n=e,!0})(o(e),t),worldToViewport:e=>{const{x:t,y:n}=i(e);return{x:Math.round(t),y:Math.round(n)}},worldToViewportRaw:i,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}=a(e);return{x:Math.round(t),y:Math.round(n)}},viewportToWorldRaw:a,viewportDimToWorld:e=>{const{w:t,h:n}=r(e);return{w:Math.round(t),h:Math.round(n)}},viewportDimToWorldRaw:r}}function Bn(e=0,t=0){const n=document.createElement("canvas");return n.width=e,n.height=t,n}var Un={createCanvas:Bn,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 l=Bn(t,n);return l.getContext("2d").drawImage(e,0,0,e.width,e.height,0,0,t,n),await createImageBitmap(l)},colorizedCanvas:function(e,t,n){const l=Bn(e.width,e.height),o=l.getContext("2d");return o.save(),o.drawImage(t,0,0),o.fillStyle=n,o.globalCompositeOperation="source-in",o.fillRect(0,0,t.width,t.height),o.restore(),o.save(),o.globalCompositeOperation="destination-over",o.drawImage(e,0,0),o.restore(),l}};const Rn=ae("Debug.js");let Vn=0,Gn=0;var $n=e=>{Vn=performance.now(),Gn=e},Fn=e=>{const t=performance.now(),n=t-Vn;n>Gn&&Rn.log(e+": "+n),Vn=t};function Ln(e,t){const n=e.x-t.x,l=e.y-t.y;return Math.sqrt(n*n+l*l)}function jn(e){return{x:e.x+e.w/2,y:e.y+e.h/2}}var Wn={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:Ln,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:jn,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 Ln(jn(e),jn(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 Hn=ae("PuzzleGraphics.js");function Yn(e,t){const n=ie.coordByPieceIdx(e,t);return{x:n.x*e.tileSize,y:n.y*e.tileSize,w:e.tileSize,h:e.tileSize}}var Qn={loadPuzzleBitmaps:async function(e){const t=await Un.loadImageToBitmap(e.info.imageUrl),n=await Un.resizeBitmap(t,e.info.width,e.info.height);return await async function(e,t,n){Hn.log("start createPuzzleTileBitmaps");const l=n.tileSize,o=n.tileMarginWidth,a=n.tileDrawSize,i=l/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),d={};function c(e){const t=`${e.top}${e.right}${e.left}${e.bottom}`;if(d[t])return d[t];const n=new Path2D,a={x:o,y:o},r=Wn.pointAdd(a,{x:l,y:0}),c=Wn.pointAdd(r,{x:0,y:l}),u=Wn.pointSub(c,{x:l,y:0});if(n.moveTo(a.x,a.y),0!==e.top)for(let l=0;l<s.length/6;l++){const t=Wn.pointAdd(a,{x:s[6*l+0]*i,y:e.top*s[6*l+1]*i}),o=Wn.pointAdd(a,{x:s[6*l+2]*i,y:e.top*s[6*l+3]*i}),r=Wn.pointAdd(a,{x:s[6*l+4]*i,y:e.top*s[6*l+5]*i});n.bezierCurveTo(t.x,t.y,o.x,o.y,r.x,r.y)}else n.lineTo(r.x,r.y);if(0!==e.right)for(let l=0;l<s.length/6;l++){const t=Wn.pointAdd(r,{x:-e.right*s[6*l+1]*i,y:s[6*l+0]*i}),o=Wn.pointAdd(r,{x:-e.right*s[6*l+3]*i,y:s[6*l+2]*i}),a=Wn.pointAdd(r,{x:-e.right*s[6*l+5]*i,y:s[6*l+4]*i});n.bezierCurveTo(t.x,t.y,o.x,o.y,a.x,a.y)}else n.lineTo(c.x,c.y);if(0!==e.bottom)for(let l=0;l<s.length/6;l++){const t=Wn.pointSub(c,{x:s[6*l+0]*i,y:e.bottom*s[6*l+1]*i}),o=Wn.pointSub(c,{x:s[6*l+2]*i,y:e.bottom*s[6*l+3]*i}),a=Wn.pointSub(c,{x:s[6*l+4]*i,y:e.bottom*s[6*l+5]*i});n.bezierCurveTo(t.x,t.y,o.x,o.y,a.x,a.y)}else n.lineTo(u.x,u.y);if(0!==e.left)for(let l=0;l<s.length/6;l++){const t=Wn.pointSub(u,{x:-e.left*s[6*l+1]*i,y:s[6*l+0]*i}),o=Wn.pointSub(u,{x:-e.left*s[6*l+3]*i,y:s[6*l+2]*i}),a=Wn.pointSub(u,{x:-e.left*s[6*l+5]*i,y:s[6*l+4]*i});n.bezierCurveTo(t.x,t.y,o.x,o.y,a.x,a.y)}else n.lineTo(a.x,a.y);return d[t]=n,n}const u=Un.createCanvas(a,a),p=u.getContext("2d"),g=Un.createCanvas(a,a),h=g.getContext("2d");for(const m of t){const t=ie.decodePiece(m),l=Yn(n,t.idx),i=c(ie.decodeShape(n.shapes[t.idx]));p.clearRect(0,0,a,a),p.save(),p.lineWidth=2,p.stroke(i),p.globalCompositeOperation="source-in",p.drawImage(e,l.x-o,l.y-o,a,a,0,0,a,a),p.restore(),p.save(),p.globalCompositeOperation="source-in",p.globalAlpha=.2,p.fillStyle="black",p.fillRect(0,0,u.width,u.height),p.restore(),p.save(),p.clip(i),p.drawImage(e,l.x-o,l.y-o,a,a,0,0,a,a),p.restore(),p.save(),p.clip(i),p.strokeStyle="rgba(0,0,0,.4)",p.lineWidth=0,p.shadowColor="black",p.shadowBlur=2,p.shadowOffsetX=-1,p.shadowOffsetY=-1,p.stroke(i),p.restore(),p.save(),p.clip(i),p.strokeStyle="rgba(255,255,255,.4)",p.lineWidth=0,p.shadowColor="white",p.shadowBlur=2,p.shadowOffsetX=1,p.shadowOffsetY=1,p.stroke(i),p.restore(),h.clearRect(0,0,a,a),h.save(),h.lineWidth=1,h.stroke(i),h.globalCompositeOperation="source-in",h.drawImage(e,l.x-o,l.y-o,a,a,0,0,a,a),h.restore(),p.drawImage(g,0,0),r[t.idx]=await createImageBitmap(u)}return Hn.log("end createPuzzleTileBitmaps"),r}(n,e.tiles,e.info)}};const qn={};function Zn(e,t){let n=0;for(const l of qn[e].players){if(ie.decodePlayer(l).id===t)return n;n++}return-1}function Kn(e,t){const n=Zn(e,t);return-1===n?null:ie.decodePlayer(qn[e].players[n])}function Xn(e,t,n){const l=Zn(e,t);-1===l?qn[e].players.push(ie.encodePlayer(n)):qn[e].players[l]=ie.encodePlayer(n)}function Jn(e,t){return-1!==Zn(e,t)}function el(e){return qn[e]?qn[e].players.map(ie.decodePlayer):[]}function tl(e){return qn[e].puzzle.tiles.length}function nl(e){return qn[e].scoreMode||Z.FINAL}function ll(e){return qn[e].snapMode||ee.NORMAL}function ol(e){return al(e)===tl(e)}function al(e){let t=0;for(const n of qn[e].puzzle.tiles)-1===ie.decodePiece(n).owner&&t++;return t}function il(e,t,n){const l=Kn(e,t);if(null!==l){for(const e of Object.keys(n))l[e]=n[e];Xn(e,t,l)}}function sl(e,t){for(const n of Object.keys(t))qn[e].puzzle.data[n]=t[n]}function rl(e,t,n){for(const l of Object.keys(n)){const o=ie.decodePiece(qn[e].puzzle.tiles[t]);o[l]=n[l],qn[e].puzzle.tiles[t]=ie.encodePiece(o)}}const dl=(e,t)=>ie.decodePiece(qn[e].puzzle.tiles[t]),cl=(e,t)=>dl(e,t).group,ul=(e,t)=>{const n=qn[e].puzzle.info;return 0===t||t===n.tilesX-1||t===n.tiles-n.tilesX||t===n.tiles-1},pl=(e,t)=>{const n=qn[e].puzzle.info,l={x:(n.table.width-n.width)/2,y:(n.table.height-n.height)/2},o=function(e,t){const n=qn[e].puzzle.info,l=ie.coordByPieceIdx(n,t),o=l.x*n.tileSize,a=l.y*n.tileSize;return{x:o,y:a}}(e,t);return Wn.pointAdd(l,o)},gl=(e,t)=>dl(e,t).pos,hl=e=>{const t=El(e),n=_l(e),l=Math.round(t/4),o=Math.round(n/4);return{x:0-l,y:0-o,w:t+2*l,h:n+2*o}},ml=(e,t)=>{const n=wl(e),l=dl(e,t);return{x:l.pos.x,y:l.pos.y,w:n,h:n}},yl=(e,t)=>dl(e,t).z,fl=(e,t)=>{for(const n of qn[e].puzzle.tiles){const e=ie.decodePiece(n);if(e.owner===t)return e.idx}return-1},vl=e=>qn[e].puzzle.info.tileDrawSize,wl=e=>qn[e].puzzle.info.tileSize,bl=e=>qn[e].puzzle.data.maxGroup,kl=e=>qn[e].puzzle.data.maxZ;function xl(e,t){const n=qn[e].puzzle.info,l=ie.coordByPieceIdx(n,t);return[l.y>0?t-n.tilesX:-1,l.x<n.tilesX-1?t+1:-1,l.y<n.tilesY-1?t+n.tilesX:-1,l.x>0?t-1:-1]}const Cl=(e,t,n)=>{for(const l of t)rl(e,l,{z:n})},Al=(e,t,n)=>{const l=gl(e,t);rl(e,t,{pos:Wn.pointAdd(l,n)})},Sl=(e,t,n)=>{const l=vl(e),o=hl(e),a=n;for(const i of t){const t=dl(e,i);t.pos.x+n.x<o.x?a.x=Math.max(o.x-t.pos.x,a.x):t.pos.x+l+n.x>o.x+o.w&&(a.x=Math.min(o.x+o.w-t.pos.x+l,a.x)),t.pos.y+n.y<o.y?a.y=Math.max(o.y-t.pos.y,a.y):t.pos.y+l+n.y>o.y+o.h&&(a.y=Math.min(o.y+o.h-t.pos.y+l,a.y))}for(const i of t)Al(e,i,a)},Tl=(e,t)=>dl(e,t).owner,Pl=(e,t)=>{for(const n of t)rl(e,n,{owner:-1,z:1})},zl=(e,t,n)=>{for(const l of t)rl(e,l,{owner:n})};function Il(e,t){const n=qn[e].puzzle.tiles,l=ie.decodePiece(n[t]),o=[];if(l.group)for(const a of n){const e=ie.decodePiece(a);e.group===l.group&&o.push(e.idx)}else o.push(l.idx);return o}const Dl=(e,t)=>{const n=Kn(e,t);return n?n.points:0},El=e=>qn[e].puzzle.info.table.width,_l=e=>qn[e].puzzle.info.table.height;var Ml={setGame:function(e,t){qn[e]=t},exists:function(e){return!!qn[e]||!1},playerExists:Jn,getActivePlayers:function(e,t){const n=t-30*N;return el(e).filter((e=>e.ts>=n))},getIdlePlayers:function(e,t){const n=t-30*N;return el(e).filter((e=>e.ts<n&&e.points>0))},addPlayer:function(e,t,n){Jn(e,t)?il(e,t,{ts:n}):Xn(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:al,getPieceCount:tl,getImageUrl:function(e){return qn[e].puzzle.info.imageUrl},setImageUrl:function(e,t){qn[e].puzzle.info.imageUrl=t},get:function(e){return qn[e]||null},getAllGames:function(){return Object.values(qn).sort(((e,t)=>ol(e.id)===ol(t.id)?t.puzzle.data.started-e.puzzle.data.started:ol(e.id)?1:-1))},getPlayerBgColor:(e,t)=>{const n=Kn(e,t);return n?n.bgcolor:null},getPlayerColor:(e,t)=>{const n=Kn(e,t);return n?n.color:null},getPlayerName:(e,t)=>{const n=Kn(e,t);return n?n.name:null},getPlayerIndexById:Zn,getPlayerIdByIndex:function(e,t){return qn[e].players.length>t?ie.decodePlayer(qn[e].players[t]).id:null},changePlayer:il,setPlayer:Xn,setPiece:function(e,t,n){qn[e].puzzle.tiles[t]=ie.encodePiece(n)},setPuzzleData:function(e,t){qn[e].puzzle.data=t},getTableWidth:El,getTableHeight:_l,getPuzzle:e=>qn[e].puzzle,getRng:e=>qn[e].rng.obj,getPuzzleWidth:e=>qn[e].puzzle.info.width,getPuzzleHeight:e=>qn[e].puzzle.info.height,getPiecesSortedByZIndex:function(e){return qn[e].puzzle.tiles.map(ie.decodePiece).sort(((e,t)=>e.z-t.z))},getFirstOwnedPiece:(e,t)=>{const n=fl(e,t);return n<0?null:qn[e].puzzle.tiles[n]},getPieceDrawOffset:e=>qn[e].puzzle.info.tileDrawOffset,getPieceDrawSize:vl,getFinalPiecePos:pl,getStartTs:e=>qn[e].puzzle.data.started,getFinishTs:e=>qn[e].puzzle.data.finished,handleInput:function(e,t,n,l,o){const a=qn[e].puzzle,i=function(e,t){return t in qn[e].evtInfos?qn[e].evtInfos[t]:{_last_mouse:null,_last_mouse_down:null}}(e,t),s=[],r=()=>{s.push([Yt,a.data])},d=t=>{s.push([Qt,ie.encodePiece(dl(e,t))])},c=e=>{for(const t of e)d(t)},u=()=>{const n=Kn(e,t);n&&s.push([qt,ie.encodePlayer(n)])},p=n[0];if(p===Vt){const o=n[1];il(e,t,{bgcolor:o,ts:l}),u()}else if(p===Gt){const o=n[1];il(e,t,{color:o,ts:l}),u()}else if(p===$t){const o=`${n[1]}`.substr(0,16);il(e,t,{name:o,ts:l}),u()}else if(p===Mt){const o=n[1],a=n[2],i=Kn(e,t);if(i){const n=i.x-o,s=i.y-a;il(e,t,{ts:l,x:n,y:s}),u()}}else if(p===Nt){const o={x:n[1],y:n[2]};il(e,t,{d:1,ts:l}),u(),i._last_mouse_down=o;const a=((e,t)=>{const n=qn[e].puzzle.info,l=qn[e].puzzle.tiles;let o=-1,a=-1;for(let i=0;i<l.length;i++){const e=ie.decodePiece(l[i]);if(0!==e.owner)continue;const s={x:e.pos.x,y:e.pos.y,w:n.tileSize,h:n.tileSize};Wn.pointInBounds(t,s)&&(-1===o||e.z>o)&&(o=e.z,a=i)}return a})(e,o);if(a>=0){const n=kl(e)+1;sl(e,{maxZ:n}),r();const l=Il(e,a);Cl(e,l,kl(e)),zl(e,l,t),c(l)}i._last_mouse=o}else if(p===Bt){const o=n[1],a=n[2],s={x:o,y:a};if(null===i._last_mouse_down)il(e,t,{x:o,y:a,ts:l}),u();else{const n=fl(e,t);if(n>=0){il(e,t,{x:o,y:a,ts:l}),u();const r=Il(e,n);let d=Wn.pointInBounds(s,hl(e))&&Wn.pointInBounds(i._last_mouse_down,hl(e));for(const t of r){const n=ml(e,t);if(Wn.pointInBounds(s,n)){d=!0;break}}if(d){const t=o-i._last_mouse_down.x,n=a-i._last_mouse_down.y;Sl(e,r,{x:t,y:n}),c(r)}}else il(e,t,{ts:l}),u();i._last_mouse_down=s}i._last_mouse=s}else if(p===Ot){const s={x:n[1],y:n[2]},p=0;i._last_mouse_down=null;const g=fl(e,t);if(g>=0){const n=Il(e,g);zl(e,n,0),c(n);const i=gl(e,g),s=pl(e,g);let h=!1;if(ll(e)===ee.REAL){for(const t of n)if(ul(e,t)){h=!0;break}}else h=!0;if(h&&Wn.pointDistance(s,i)<a.info.snapDistance){const a=Wn.pointSub(s,i);Sl(e,n,a),Pl(e,n),c(n);let d=Dl(e,t);nl(e)===Z.FINAL?d+=n.length:nl(e)===Z.ANY&&(d+=1),il(e,t,{d:p,ts:l,points:d}),u(),al(e)===tl(e)&&(sl(e,{finished:l}),r()),o&&o(t)}else{const n=(e,t,n,l)=>{const o=qn[e].puzzle.info;if(n<0)return!1;if(((e,t,n)=>{const l=cl(e,t),o=cl(e,n);return!(!l||l!==o)})(e,t,n))return!1;const a=gl(e,t),i=Wn.pointAdd(gl(e,n),{x:l[0]*o.tileSize,y:l[1]*o.tileSize});if(Wn.pointDistance(a,i)<o.snapDistance){const l=Wn.pointSub(i,a);let o=Il(e,t);if(Sl(e,o,l),((e,t,n)=>{const l=qn[e].puzzle.tiles,o=cl(e,t),a=cl(e,n);let i;const s=[];o&&s.push(o),a&&s.push(a),o?i=o:a?i=a:(sl(e,{maxGroup:bl(e)+1}),r(),i=bl(e));if(rl(e,t,{group:i}),d(t),rl(e,n,{group:i}),d(n),s.length>0)for(const r of l){const t=ie.decodePiece(r);s.includes(t.group)&&(rl(e,t.idx,{group:i}),d(t.idx))}})(e,t,n),o=Il(e,t),((e,t)=>-1===Tl(e,t))(e,n))Pl(e,o);else{const t=((e,t)=>{let n=0;for(const l of t){const t=yl(e,l);t>n&&(n=t)}return n})(e,o);Cl(e,o,t)}return c(o),!0}return!1};let a=!1;for(const t of Il(e,g)){const l=xl(e,t);if(n(e,t,l[0],[0,1])||n(e,t,l[1],[-1,0])||n(e,t,l[2],[0,-1])||n(e,t,l[3],[1,0])){a=!0;break}}if(a&&nl(e)===Z.ANY){const n=Dl(e,t)+1;il(e,t,{d:p,ts:l,points:n}),u()}else il(e,t,{d:p,ts:l}),u();a&&ll(e)===ee.REAL&&al(e)===tl(e)&&(sl(e,{finished:l}),r()),a&&o&&o(t)}}else il(e,t,{d:p,ts:l}),u();i._last_mouse=s}else if(p===Ut){const o=n[1],a=n[2];il(e,t,{x:o,y:a,ts:l}),u(),i._last_mouse={x:o,y:a}}else if(p===Rt){const o=n[1],a=n[2];il(e,t,{x:o,y:a,ts:l}),u(),i._last_mouse={x:o,y:a}}else il(e,t,{ts:l}),u();return function(e,t,n){qn[e].evtInfos[t]=n}(e,t,i),s}};let Nl=-10,Ol=20,Bl=2,Ul=15;class Rl{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=Nl+Math.random()*Ol,this.vy=-1*(Bl+Math.random()*Ul),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<t;n++){const t=10+Math.floor(21*Math.random()),n=5+5*Math.random(),l=2*Math.PI/t,o=Math.random()*l;for(let a=0;a<t;a++)e.push(new Vl(this,a*l+o,n))}}}class Vl{constructor(e,t,n){this.px=e.px,this.py=e.py,this.vx=Math.cos(t)*n,this.vy=Math.sin(t)*n,this.color=e.color,this.duration=40+Math.floor(20*Math.random()),this.alive=!0,this.radius=0}update(){this.vx+=0,this.vy+=.1,this.px+=this.vx,this.py+=this.vy,this.radius=3,this.duration--,this.duration<=0&&(this.alive=!1)}draw(e){e.beginPath(),e.arc(this.px,this.py,this.radius,0,2*Math.PI,!1),e.fillStyle=this.color,e.lineWidth=1,e.fill()}}class Gl{constructor(e,t){this.canvas=e,this.rng=t,this.ctx=this.canvas.getContext("2d"),this.resize(),this.readyBombs=[],this.explodedBombs=[],this.particles=[],window.addEventListener("resize",(()=>{this.resize()}))}setSpeedParams(){let e=0,t=0;for(;e<this.canvas.height&&t>=0;)t+=1,e+=t;Bl=t/2,Ul=t-Bl;const n=1/4*this.canvas.width/(t/2);Nl=-n,Ol=2*n}resize(){this.setSpeedParams()}init(){this.readyBombs=[],this.explodedBombs=[],this.particles=[];for(let e=0;e<1;e++)this.readyBombs.push(new Rl(this.rng))}update(){100*Math.random()<5&&this.readyBombs.push(new Rl(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<this.readyBombs.length;e++)this.readyBombs[e].draw(this.ctx);for(let e=0;e<this.explodedBombs.length;e++)this.explodedBombs[e].draw(this.ctx);for(let e=0;e<this.particles.length;e++)this.particles[e].draw(this.ctx)}}const $l={"./grab.png":En,"./grab_mask.png":_n,"./hand.png":Mn,"./hand_mask.png":Nn},Fl={"./click.mp3":Dn};let Ll=!0,jl=!0;let Wl=!0;async function Hl(e,t,n,l,o,a){void 0===window.DEBUG&&(window.DEBUG=!1);const i=Fl["./click.mp3"].default,s=new Audio(i),r=await Un.loadImageToBitmap($l["./grab.png"].default),d=await Un.loadImageToBitmap($l["./hand.png"].default),c=await Un.loadImageToBitmap($l["./grab_mask.png"].default),u=await Un.loadImageToBitmap($l["./hand_mask.png"].default),p=r.width,g=Math.round(p/2),h=r.height,m=Math.round(h/2),y={},f=async e=>{const t=e.color+" "+e.d;if(!y[t]){const n=e.d?r:d;if(e.color){const l=e.d?c:u;y[t]=await createImageBitmap(Un.colorizedCanvas(n,l,e.color))}else y[t]=n}return y[t]},v=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,Wl=!0})),t}(o,Un.createCanvas()),w={final:!1,log:[],logPointer:0,speeds:[.5,1,2,5,10,20,50,100,250,500],speedIdx:1,paused:!1,lastRealTs:0,lastGameTs:0,gameStartTs:0,skipNonActionPhases:!0,dataOffset:0};rn.onConnectionStateChange((e=>{a.setConnectionState(e)}));const b=async e=>{const t=w.dataOffset;w.dataOffset+=1e4;const n=await rn.requestReplayData(e,t);return w.log=w.log.slice(w.logPointer),w.logPointer=0,w.log.push(...n.log),0===n.log.length&&(w.final=!0),n};let k=()=>0;const x=async()=>{if("play"===l){const l=await rn.connect(n,e,t),o=ie.decodeGame(l);Ml.setGame(o.id,o),k=()=>O()}else{if("replay"!==l)throw"[ 2020-12-22 MODE invalid, must be play|replay ]";{const t=await b(e);if(!t.game)throw"[ 2021-05-29 no game received ]";const n=ie.decodeGame(t.game);Ml.setGame(n.id,n),w.lastRealTs=O(),w.gameStartTs=parseInt(t.log[0][4],10),w.lastGameTs=w.gameStartTs,k=()=>w.lastGameTs}}Wl=!0};await x();const C=Ml.getPieceDrawOffset(e),A=Ml.getPieceDrawSize(e),S=Ml.getPuzzleWidth(e),T=Ml.getPuzzleHeight(e),P=Ml.getTableWidth(e),z=Ml.getTableHeight(e),I={x:(P-S)/2,y:(z-T)/2},D={w:S,h:T},E={w:A,h:A},_=await Qn.loadPuzzleBitmaps(Ml.getPuzzle(e)),N=new Gl(v,Ml.getRng(e));N.init();const B=v.getContext("2d");v.classList.add("loaded");const U=On();U.move(-(P-v.width)/2,-(z-v.height)/2);const R=function(e,t,n,l){let o=[],a=!0,i=!1,s=!1,r=!1,d=!1,c=!1,u=!1,p=!1;const g=(e,t)=>{const l=n.viewportToWorld({x:e,y:t});return[l.x,l.y]},h=e=>g(e.offsetX,e.offsetY),m=()=>g(e.width/2,e.height/2),y=(e,t)=>{a&&("Shift"===t.key?p=e:"ArrowUp"===t.key||"w"===t.key||"W"===t.key?r=e:"ArrowDown"===t.key||"s"===t.key||"S"===t.key?d=e:"ArrowLeft"===t.key||"a"===t.key||"A"===t.key?i=e:"ArrowRight"===t.key||"d"===t.key||"D"===t.key?s=e:"q"===t.key?u=e:"e"===t.key&&(c=e))};let f=null;e.addEventListener("mousedown",(e=>{f=h(e),0===e.button&&v([Nt,...f])})),e.addEventListener("mouseup",(e=>{f=h(e),0===e.button&&v([Ot,...f])})),e.addEventListener("mousemove",(e=>{f=h(e),v([Bt,...f])})),e.addEventListener("wheel",(e=>{if(f=h(e),n.canZoom(e.deltaY<0?"in":"out")){const t=e.deltaY<0?Ut:Rt;v([t,...f])}})),t.addEventListener("keydown",(e=>y(!0,e))),t.addEventListener("keyup",(e=>y(!1,e))),t.addEventListener("keypress",(e=>{a&&(" "===e.key&&v([Ft]),"replay"===l&&("I"!==e.key&&"i"!==e.key||v([Wt]),"O"!==e.key&&"o"!==e.key||v([Ht]),"P"!==e.key&&"p"!==e.key||v([jt])),"F"!==e.key&&"f"!==e.key||(Ll=!Ll,Wl=!0),"G"!==e.key&&"g"!==e.key||(jl=!jl,Wl=!0),"M"!==e.key&&"m"!==e.key||v([Lt]))}));const v=e=>{o.push(e)};return{addEvent:v,consumeAll:()=>{if(0===o.length)return[];const e=o.slice();return o=[],e},createKeyEvents:()=>{const e=(i?1:0)-(s?1:0),t=(r?1:0)-(d?1:0);if(0!==e||0!==t){const l=(p?24:12)*Math.sqrt(n.getCurrentZoom()),o=n.viewportDimToWorld({w:e*l,h:t*l});v([Mt,o.w,o.h]),f&&(f[0]-=o.w,f[1]-=o.h)}if(c&&u);else if(c){if(n.canZoom("in")){const e=f||m();v([Ut,...e])}}else if(u&&n.canZoom("out")){const e=f||m();v([Rt,...e])}},setHotkeys:e=>{a=e}}}(v,window,U,l),V=Ml.getImageUrl(e),G=()=>{const t=Ml.getStartTs(e),n=Ml.getFinishTs(e),l=k();a.setFinished(!!n),a.setDuration((n||l)-t)};G(),a.setPiecesDone(Ml.getFinishedPiecesCount(e)),a.setPiecesTotal(Ml.getPieceCount(e));const $=k();a.setActivePlayers(Ml.getActivePlayers(e,$)),a.setIdlePlayers(Ml.getIdlePlayers(e,$));const F=!!Ml.getFinishTs(e);let L=F;const j=()=>L&&!F,W=()=>{const e=localStorage.getItem("sound_enabled");return null!==e&&"1"===e},H=()=>Ml.getPlayerBgColor(e,t)||localStorage.getItem("bg_color")||"#222222",Y=()=>Ml.getPlayerColor(e,t)||localStorage.getItem("player_color")||"#ffffff";let Q="",q="",Z=!1;const K=e=>{Z=e;const[t,n]=e?[Q,"grab"]:[q,"default"];v.style.cursor=`url('${t}') ${g} ${m}, ${n}`},X=e=>{Q=Un.colorizedCanvas(r,c,e).toDataURL(),q=Un.colorizedCanvas(d,u,e).toDataURL(),K(Z)};X(Y());const J=()=>{a.setReplaySpeed&&a.setReplaySpeed(w.speeds[w.speedIdx]),a.setReplayPaused&&a.setReplayPaused(w.paused)},ee=()=>{w.speedIdx+1<w.speeds.length&&(w.speedIdx++,J())},te=()=>{w.speedIdx>=1&&(w.speedIdx--,J())},ne=()=>{w.paused=!w.paused,J()},le=[];let oe;let ae;if("play"===l?le.push(setInterval((()=>{G()}),1e3)):"replay"===l&&J(),"play"===l)rn.onServerChange((n=>{n[0],n[1],n[2];const l=n[3];for(const[o,a]of l)switch(o){case qt:{const n=ie.decodePlayer(a);n.id!==t&&(Ml.setPlayer(e,n.id,n),Wl=!0)}break;case Qt:{const t=ie.decodePiece(a);Ml.setPiece(e,t.idx,t),Wl=!0}break;case Yt:Ml.setPuzzleData(e,a),Wl=!0}L=!!Ml.getFinishTs(e)}));else if("replay"===l){const t=(t,n)=>{const l=t;if(l[0]===Dt){const t=l[1];return Ml.addPlayer(e,t,n),!0}if(l[0]===Et){const t=Ml.getPlayerIdByIndex(e,l[1]);if(!t)throw"[ 2021-05-17 player not found (update player) ]";return Ml.addPlayer(e,t,n),!0}if(l[0]===_t){const t=Ml.getPlayerIdByIndex(e,l[1]);if(!t)throw"[ 2021-05-17 player not found (handle input) ]";const o=l[2];return Ml.handleInput(e,t,o,n),!0}return!1};let n=w.lastGameTs;const l=async()=>{w.logPointer+1>=w.log.length&&await b(e);const o=O();if(w.paused)return w.lastRealTs=o,void(oe=setTimeout(l,50));const a=(o-w.lastRealTs)*w.speeds[w.speedIdx];let i=w.lastGameTs+a;for(;;){if(w.paused)break;const e=w.logPointer+1;if(e>=w.log.length)break;const l=w.log[w.logPointer],o=n+l[l.length-1],a=w.log[e],s=a[a.length-1],r=o+s;if(r>i){w.skipNonActionPhases&&i+500*M<r&&(i+=s);break}n=o,t(a,r)&&(Wl=!0),w.logPointer=e}w.lastRealTs=o,w.lastGameTs=i,G(),w.final||(oe=setTimeout(l,50))};l()}let se=null;return ae=(e=>{let t=!1;const n=e.fps||60,l=e.slow||1,o=e.update,a=e.render,i=window.requestAnimationFrame,s=1/n,r=l*s;let d,c=0,u=window.performance.now();const p=()=>{for(d=window.performance.now(),c+=Math.min(1,(d-u)/1e3);c>r;)c-=r,o(s);a(c/l),u=d,t||i(p)};return i(p),{stop:()=>{t=!0}}})({update:()=>{R.createKeyEvents();for(const n of R.consumeAll())if("play"===l){const l=n[0];if(l===Mt){const e=n[1],t=n[2],l=U.worldDimToViewport({w:e,h:t});Wl=!0,U.move(l.w,l.h)}else if(l===Bt){if(se&&!Ml.getFirstOwnedPiece(e,t)){const e={x:n[1],y:n[2]},t=U.worldToViewport(e),l=Math.round(t.x-se.x),o=Math.round(t.y-se.y);Wl=!0,U.move(l,o),se=t}}else if(l===Gt)X(n[1]);else if(l===Nt){const e={x:n[1],y:n[2]};se=U.worldToViewport(e),K(!0)}else if(l===Ot)se=null,K(!1);else if(l===Ut){const e={x:n[1],y:n[2]};Wl=!0,U.zoom("in",U.worldToViewport(e))}else if(l===Rt){const e={x:n[1],y:n[2]};Wl=!0,U.zoom("out",U.worldToViewport(e))}else l===Ft?a.togglePreview():l===Lt&&a.toggleSoundsEnabled();const o=k();Ml.handleInput(e,t,n,o,(e=>{W()&&s.play()})).length>0&&(Wl=!0),rn.sendClientEvent(n)}else if("replay"===l){const e=n[0];if(e===jt)ne();else if(e===Ht)te();else if(e===Wt)ee();else if(e===Mt){const e=n[1],t=n[2];Wl=!0,U.move(e,t)}else if(e===Bt){if(se){const e={x:n[1],y:n[2]},t=U.worldToViewport(e),l=Math.round(t.x-se.x),o=Math.round(t.y-se.y);Wl=!0,U.move(l,o),se=t}}else if(e===Nt){const e={x:n[1],y:n[2]};se=U.worldToViewport(e)}else if(e===Ot)se=null;else if(e===Ut){const e={x:n[1],y:n[2]};Wl=!0,U.zoom("in",U.worldToViewport(e))}else if(e===Rt){const e={x:n[1],y:n[2]};Wl=!0,U.zoom("out",U.worldToViewport(e))}else e===Ft&&a.togglePreview()}L=!!Ml.getFinishTs(e),j()&&(N.update(),Wl=!0)},render:async()=>{if(!Wl)return;const n=k();let o,i,s;window.DEBUG&&$n(0),B.fillStyle=H(),B.fillRect(0,0,v.width,v.height),window.DEBUG&&Fn("clear done"),o=U.worldToViewportRaw(I),i=U.worldDimToViewportRaw(D),B.fillStyle="rgba(255, 255, 255, .3)",B.fillRect(o.x,o.y,i.w,i.h),window.DEBUG&&Fn("board done");const r=Ml.getPiecesSortedByZIndex(e);window.DEBUG&&Fn("get tiles done"),i=U.worldDimToViewportRaw(E);for(const e of r)(-1===e.owner?Ll:jl)&&(s=_[e.idx],o=U.worldToViewportRaw({x:C+e.pos.x,y:C+e.pos.y}),B.drawImage(s,0,0,s.width,s.height,o.x,o.y,i.w,i.h));window.DEBUG&&Fn("tiles done");const d=[];for(const a of Ml.getActivePlayers(e,n))c=a,("replay"===l||c.id!==t)&&(s=await f(a),o=U.worldToViewport(a),B.drawImage(s,o.x-g,o.y-m),d.push([`${a.name} (${a.points})`,o.x,o.y+h]));var c;B.fillStyle="white",B.textAlign="center";for(const[e,t,l]of d)B.fillText(e,t,l);window.DEBUG&&Fn("players done"),a.setActivePlayers(Ml.getActivePlayers(e,n)),a.setIdlePlayers(Ml.getIdlePlayers(e,n)),a.setPiecesDone(Ml.getFinishedPiecesCount(e)),window.DEBUG&&Fn("HUD done"),j()&&N.render(),Wl=!1}}),{setHotkeys:e=>{R.setHotkeys(e)},onBgChange:e=>{localStorage.setItem("bg_color",e),R.addEvent([Vt,e])},onColorChange:e=>{localStorage.setItem("player_color",e),R.addEvent([Gt,e])},onNameChange:e=>{localStorage.setItem("player_name",e),R.addEvent([$t,e])},onSoundsEnabledChange:e=>{localStorage.setItem("sound_enabled",e?"1":"0")},replayOnSpeedUp:ee,replayOnSpeedDown:te,replayOnPauseToggle:ne,replayOnSkipToggle:()=>{w.skipNonActionPhases=!w.skipNonActionPhases},previewImageUrl:V,player:{background:H(),color:Y(),name:Ml.getPlayerName(e,t)||localStorage.getItem("player_name")||"anon",soundsEnabled:W()},disconnect:rn.disconnect,connect:x,unload:()=>{le.forEach((e=>{clearInterval(e)})),oe&&clearTimeout(oe),ae&&ae.stop()}}}var Yl=e({name:"game",components:{PuzzleStatus:ft,Scores:pt,SettingsOverlay:wt,PreviewOverlay:At,ConnectionOverlay:dn,HelpOverlay:mn},data:()=>({activePlayers:[],idlePlayers:[],finished:!1,duration:0,piecesDone:0,piecesTotal:0,overlay:"",connectionState:0,g:{player:{background:"",color:"",name:"",soundsEnabled:!1},previewImageUrl:"",setHotkeys:e=>{},onBgChange:e=>{},onColorChange:e=>{},onNameChange:e=>{},onSoundsEnabledChange:e=>{},connect:()=>{},disconnect:()=>{},unload:()=>{}}}),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.$watch((()=>this.g.player.soundsEnabled),(e=>{this.g.onSoundsEnabledChange(e)})),this.g=await Hl(`${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)},toggleSoundsEnabled:()=>{this.g.player.soundsEnabled=!this.g.player.soundsEnabled}}))},unmounted(){this.g.unload(),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 Ql={id:"game"},ql={class:"menu"},Zl={class:"tabs"},Kl=s("🧩 Puzzles");Yl.render=function(e,o,s,r,d,c){const u=a("settings-overlay"),g=a("preview-overlay"),h=a("help-overlay"),m=a("connection-overlay"),y=a("puzzle-status"),f=a("router-link"),v=a("scores");return i(),t("div",Ql,[p(n(u,{onBgclick:o[1]||(o[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":o[2]||(o[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[x,"settings"===e.overlay]]),p(n(g,{onBgclick:o[3]||(o[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[x,"preview"===e.overlay]]),p(n(h,{onBgclick:o[4]||(o[4]=t=>e.toggle("help",!0))},null,512),[[x,"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",ql,[n("div",Zl,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:l((()=>[Kl])),_:1}),n("div",{class:"opener",onClick:o[5]||(o[5]=t=>e.toggle("preview",!1))},"🖼️ Preview"),n("div",{class:"opener",onClick:o[6]||(o[6]=t=>e.toggle("settings",!0))},"🛠️ Settings"),n("div",{class:"opener",onClick:o[7]||(o[7]=t=>e.toggle("help",!0))}," Help")])]),n(v,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])};var Xl=e({name:"replay",components:{PuzzleStatus:ft,Scores:pt,SettingsOverlay:wt,PreviewOverlay:At,HelpOverlay:mn},data:()=>({activePlayers:[],idlePlayers:[],finished:!1,duration:0,piecesDone:0,piecesTotal:0,skipNoAction:!0,overlay:"",connectionState:0,g:{player:{background:"",color:"",name:"",soundsEnabled:!1},previewImageUrl:"",setHotkeys:e=>{},onBgChange:e=>{},onColorChange:e=>{},onNameChange:e=>{},onSoundsEnabledChange:e=>{},replayOnSpeedUp:()=>{},replayOnSpeedDown:()=>{},replayOnPauseToggle:()=>{},replayOnSkipToggle:()=>{},connect:()=>{},disconnect:()=>{},unload:()=>{}},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.$watch((()=>this.g.player.soundsEnabled),(e=>{this.g.onSoundsEnabledChange(e)})),this.g=await Hl(`${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},toggleSoundsEnabled:()=>{this.g.player.soundsEnabled=!this.g.player.soundsEnabled}}))},unmounted(){this.g.unload(),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 Jl={id:"replay"},eo=s("Skip no action phases: "),to={class:"menu"},no={class:"tabs"},lo=s("🧩 Puzzles");Xl.render=function(e,o,s,d,c,u){const g=a("settings-overlay"),h=a("preview-overlay"),m=a("help-overlay"),y=a("puzzle-status"),f=a("router-link"),v=a("scores");return i(),t("div",Jl,[p(n(g,{onBgclick:o[1]||(o[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":o[2]||(o[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[x,"settings"===e.overlay]]),p(n(h,{onBgclick:o[3]||(o[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[x,"preview"===e.overlay]]),p(n(m,{onBgclick:o[4]||(o[4]=t=>e.toggle("help",!0))},null,512),[[x,"help"===e.overlay]]),n(y,{finished:e.finished,duration:e.duration,piecesDone:e.piecesDone,piecesTotal:e.piecesTotal},{default:l((()=>[n("div",null,[n("div",null,r(e.replayText),1),n("div",null,[n("label",null,[eo,p(n("input",{type:"checkbox","onUpdate:modelValue":o[5]||(o[5]=t=>e.skipNoAction=t),onChange:o[6]||(o[6]=t=>e.g.replayOnSkipToggle())},null,544),[[k,e.skipNoAction]])])]),n("button",{class:"btn",onClick:o[7]||(o[7]=t=>e.g.replayOnSpeedUp())},"⏫"),n("button",{class:"btn",onClick:o[8]||(o[8]=t=>e.g.replayOnSpeedDown())},"⏬"),n("button",{class:"btn",onClick:o[9]||(o[9]=t=>e.g.replayOnPauseToggle())},"⏸️")])])),_:1},8,["finished","duration","piecesDone","piecesTotal"]),n("div",to,[n("div",no,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:l((()=>[lo])),_:1}),n("div",{class:"opener",onClick:o[10]||(o[10]=t=>e.toggle("preview",!1))},"🖼️ Preview"),n("div",{class:"opener",onClick:o[11]||(o[11]=t=>e.toggle("settings",!0))},"🛠️ Settings"),n("div",{class:"opener",onClick:o[12]||(o[12]=t=>e.toggle("help",!0))}," Help")])]),n(v,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])},(async()=>{const e=await fetch("/api/conf"),t=await e.json();const n=C({history:A(),routes:[{name:"index",path:"/",component:j},{name:"new-game",path:"/new-game",component:nt},{name:"game",path:"/g/:id",component:Yl},{name:"replay",path:"/replay/:id",component:Xl}]});n.beforeEach(((e,t)=>{t.name&&document.documentElement.classList.remove(`view-${String(t.name)}`),document.documentElement.classList.add(`view-${String(e.name)}`)}));const l=S(T);l.config.globalProperties.$config=t,l.config.globalProperties.$clientId=function(){let e=localStorage.getItem("ID");return e||(e=ie.uniqId(),localStorage.setItem("ID",e)),e}(),l.use(n),l.mount("#app")})();