diff --git a/build/public/assets/index.6748df9f.css b/build/public/assets/index.53fc6304.css similarity index 63% rename from build/public/assets/index.6748df9f.css rename to build/public/assets/index.53fc6304.css index 81fcb78..6fc63bc 100644 --- a/build/public/assets/index.6748df9f.css +++ b/build/public/assets/index.53fc6304.css @@ -1 +1 @@ -:root{--main-color:#c1b19f;--main-darker-color:#4f4e4c;--link-color:#808db0;--link-hover-color:#c5cfeb;--highlight-color:#dd7e7e;--positive-color:#64a756;--input-bg-color:#262523;--bg-color:rgba(0,0,0,.7)}body,html{margin:0;background:#2b2b2b;color:var(--main-color);height:100%}*{font-family:monospace;font-size:15px}h1,h2,h3,h4{font-size:20px}a{color:var(--link-color);text-decoration:none}a:hover{color:var(--link-hover-color)}td,th{vertical-align:top}.btn{display:inline-block;background:var(--input-bg-color);color:var(--link-color);border:solid 1px #000;padding:5px 10px;box-shadow:1px 1px 2px rgba(0,0,0,.5),0 0 1px rgba(150,150,150,.4) inset;border-radius:4px;user-select:none}.btn-big{font-size:1.5em;padding:10px 20px}.btn:hover{background:#2f2e2c;color:var(--link-hover-color);border:solid 1px #111;box-shadow:0 0 1px rgba(150,150,150,.4) inset;cursor:pointer}.btn:disabled{background:#2f2e2c;color:#8c4747!important;border:solid 1px #111;box-shadow:0 0 1px rgba(150,150,150,.4) inset;cursor:not-allowed}input{background:#333230;border-radius:4px;color:var(--main-color);padding:6px 10px;border:solid 1px #000;box-shadow:0 0 3px rgba(0,0,0,.3) inset}input:focus{border:solid 1px #686767;background:var(--input-bg-color)}.scores{position:absolute;right:0;top:0;background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7)}.timer{position:absolute;left:0;top:0;background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7)}.menu{position:absolute;top:0;left:50%;transform:translateX(-50%);background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7);z-index:2}.closed{display:none}.overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:10;background:var(--bg-color)}.overlay.transparent{background:0 0}.overlay-content{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7);z-index:1}.connection-lost .overlay-content{padding:20px;text-align:center}.preview{position:absolute;top:20px;left:20px;bottom:20px;right:20px}.preview .img{height:100%;width:100%;position:absolute;background-repeat:no-repeat;background-position:center;background-size:contain}.menu .opener{display:inline-block;margin-right:10px;color:var(--link-color)}.menu .opener:last-child{margin-right:0}.menu .opener:hover{color:var(--link-hover-color);cursor:pointer}kbd{background-color:#eee;border-radius:3px;border:1px solid #b4b4b4;box-shadow:0 1px 1px rgba(0,0,0,.2),0 2px 0 0 rgba(255,255,255,.7) inset;color:#333;display:inline-block;font-size:.85em;font-weight:700;line-height:1;padding:2px 4px;white-space:nowrap}.hint{color:var(--main-darker-color)}.bit{background:#3b3737;border-radius:.5em;padding:.25em .5em;display:inline-block;margin:0 .25em .25em 0;cursor:pointer}.bit.on{color:var(--positive-color)}.upload-image-teaser{text-align:center}.upload-image-teaser .btn{margin-bottom:.5em}table label{line-height:32px}.nav{list-style:none;padding:0}.nav li{display:inline-block;margin-right:1em}.image-list{overflow:scroll}.image-list-inner{white-space:nowrap}.imageteaser{width:150px;height:100px;display:inline-block;margin:5px;background-size:contain;background-position:center;background-repeat:no-repeat;background-color:#222;cursor:pointer}.game-teaser-wrap{display:inline-block;width:20%;padding:5px;box-sizing:border-box}.game-teaser{display:block;background-repeat:no-repeat;background-position:center;background-size:contain;position:relative;padding-top:56.25%;width:100%;background-color:#222}.game-info{position:absolute;top:0;left:0;right:0;bottom:0;width:100%;height:100%}.game-info-text{position:absolute;top:0;background:var(--bg-color);padding:5px}.game-replay{position:absolute;top:0;right:0}html.view-game{overflow:hidden}html.view-game body{overflow:hidden}html.view-replay{overflow:hidden}html.view-replay body{overflow:hidden}.imageteaser{position:relative}.imageteaser .edit{display:none;position:absolute}.imageteaser:hover .edit{display:inline-block}.input[data-v-39ed99c7]{margin-bottom:.5em}.autocomplete[data-v-39ed99c7]{position:relative}.autocomplete ul[data-v-39ed99c7]{list-style:none;padding:0;margin:0;position:absolute;left:0;right:0;background:#333230;top:-.5em}.autocomplete ul li[data-v-39ed99c7]{position:relative;padding:.5em .5em .5em 1.5em;cursor:pointer}.autocomplete ul li.active[data-v-39ed99c7]{color:var(--link-hover-color);background:var(--input-bg-color)}.autocomplete ul li.active[data-v-39ed99c7]:before{content:'β–Ά';display:block;position:absolute;left:.5em}.new-image-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}.new-image-dialog .area-image{grid-area:image;margin:20px}.new-image-dialog .area-image.no-image{align-content:center;display:grid;text-align:center;border:dashed 6px;position:relative}.new-image-dialog .area-image .has-image{position:relative;width:100%;height:100%}.new-image-dialog .area-image .has-image .remove{position:absolute;top:.5em;left:.5em}.new-image-dialog .area-settings{grid-area:settings}.new-image-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.new-image-dialog .area-buttons{align-self:end;grid-area:buttons}.new-image-dialog .area-buttons button{width:100%;margin-top:.5em}.new-image-dialog .upload{position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer}.new-image-dialog .upload .btn{position:absolute;top:50%;transform:translate(-50%,-50%)}.edit-image-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}.edit-image-dialog .area-image{grid-area:image;margin:20px}.edit-image-dialog .area-image.no-image{align-content:center;display:grid;text-align:center;border:dashed 6px;position:relative}.edit-image-dialog .area-image .has-image{position:relative;width:100%;height:100%}.edit-image-dialog .area-image .has-image .remove{position:absolute;top:.5em;left:.5em}.edit-image-dialog .area-settings{grid-area:settings}.edit-image-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.edit-image-dialog .area-buttons{align-self:end;grid-area:buttons}.edit-image-dialog .area-buttons button{width:100%;margin-top:.5em}.new-game-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}.new-game-dialog .area-image{grid-area:image;margin:20px}.new-game-dialog .area-settings{grid-area:settings}.new-game-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.new-game-dialog .area-buttons{align-self:end;grid-area:buttons}.new-game-dialog .area-buttons button{width:100%}.new-game-dialog .has-image{position:relative;width:100%;height:100%}.new-game-dialog .has-image .remove{position:absolute;top:.5em;left:.5em} \ No newline at end of file +:root{--main-color:#c1b19f;--main-darker-color:#4f4e4c;--link-color:#808db0;--link-hover-color:#c5cfeb;--highlight-color:#dd7e7e;--positive-color:#64a756;--input-bg-color:#262523;--bg-color:rgba(0,0,0,.7)}body,html{margin:0;background:#2b2b2b;color:var(--main-color);height:100%}*{font-family:monospace;font-size:15px}h1,h2,h3,h4{font-size:20px}a{color:var(--link-color);text-decoration:none}a:hover{color:var(--link-hover-color)}td,th{vertical-align:top}.btn{display:inline-block;background:var(--input-bg-color);color:var(--link-color);border:solid 1px #000;padding:5px 10px;box-shadow:1px 1px 2px rgba(0,0,0,.5),0 0 1px rgba(150,150,150,.4) inset;border-radius:4px;user-select:none}.btn-big{font-size:1.5em;padding:10px 20px}.btn:hover{background:#2f2e2c;color:var(--link-hover-color);border:solid 1px #111;box-shadow:0 0 1px rgba(150,150,150,.4) inset;cursor:pointer}.btn:disabled{background:#2f2e2c;color:#8c4747!important;border:solid 1px #111;box-shadow:0 0 1px rgba(150,150,150,.4) inset;cursor:not-allowed}input{background:#333230;border-radius:4px;color:var(--main-color);padding:6px 10px;border:solid 1px #000;box-shadow:0 0 3px rgba(0,0,0,.3) inset}input:focus{border:solid 1px #686767;background:var(--input-bg-color)}.scores{position:absolute;right:0;top:0;background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7)}.timer{position:absolute;left:0;top:0;background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7)}.menu{position:absolute;top:0;left:50%;transform:translateX(-50%);background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7);z-index:2}.closed{display:none}.overlay{position:absolute;top:0;left:0;right:0;bottom:0;z-index:10;background:var(--bg-color)}.overlay.transparent{background:0 0}.overlay-content{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);background:var(--bg-color);padding:5px;border:solid 1px #000;box-shadow:0 0 10px 0 rgba(0,0,0,.7);z-index:1}.connection-lost .overlay-content{padding:20px;text-align:center}.preview{position:absolute;top:20px;left:20px;bottom:20px;right:20px}.preview .img{height:100%;width:100%;position:absolute;background-repeat:no-repeat;background-position:center;background-size:contain}.menu .opener{display:inline-block;margin-right:10px;color:var(--link-color)}.menu .opener:last-child{margin-right:0}.menu .opener:hover{color:var(--link-hover-color);cursor:pointer}kbd{background-color:#eee;border-radius:3px;border:1px solid #b4b4b4;box-shadow:0 1px 1px rgba(0,0,0,.2),0 2px 0 0 rgba(255,255,255,.7) inset;color:#333;display:inline-block;font-size:.85em;font-weight:700;line-height:1;padding:2px 4px;white-space:nowrap}.hint{color:var(--main-darker-color)}.bit{background:#3b3737;border-radius:.5em;padding:.25em .5em;display:inline-block;margin:0 .25em .25em 0;cursor:pointer}.bit.on{color:var(--positive-color)}.upload-image-teaser{text-align:center}.upload-image-teaser .btn{margin-bottom:.5em}table label{line-height:32px}.nav{list-style:none;padding:0}.nav li{display:inline-block;margin-right:1em}.image-list{overflow:scroll}.image-list-inner{white-space:nowrap}.imageteaser{width:150px;height:100px;display:inline-block;margin:5px;background-size:contain;background-position:center;background-repeat:no-repeat;background-color:#222;cursor:pointer}.game-teaser-wrap{display:inline-block;width:20%;padding:5px;box-sizing:border-box}.game-teaser{display:block;background-repeat:no-repeat;background-position:center;background-size:contain;position:relative;padding-top:56.25%;width:100%;background-color:#222}.game-info{position:absolute;top:0;left:0;right:0;bottom:0;width:100%;height:100%}.game-info-text{position:absolute;top:0;background:var(--bg-color);padding:5px}.game-replay{position:absolute;top:0;right:0}html.view-game{overflow:hidden}html.view-game body{overflow:hidden}html.view-replay{overflow:hidden}html.view-replay body{overflow:hidden}.imageteaser{position:relative}.imageteaser .edit{display:none;position:absolute}.imageteaser:hover .edit{display:inline-block}.input[data-v-39ed99c7]{margin-bottom:.5em}.autocomplete[data-v-39ed99c7]{position:relative}.autocomplete ul[data-v-39ed99c7]{list-style:none;padding:0;margin:0;position:absolute;left:0;right:0;background:#333230;top:-.5em}.autocomplete ul li[data-v-39ed99c7]{position:relative;padding:.5em .5em .5em 1.5em;cursor:pointer}.autocomplete ul li.active[data-v-39ed99c7]{color:var(--link-hover-color);background:var(--input-bg-color)}.autocomplete ul li.active[data-v-39ed99c7]:before{content:'β–Ά';display:block;position:absolute;left:.5em}.new-image-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}@media (max-width:1400px){.new-image-dialog .overlay-content{grid-template-columns:auto;grid-template-rows:1fr min-content min-content;grid-template-areas:"image" "settings" "buttons"}}.new-image-dialog .area-image{grid-area:image;margin:20px}.new-image-dialog .area-image.no-image{align-content:center;display:grid;text-align:center;border:solid 6px;position:relative}.new-image-dialog .area-image.droppable{border:dashed 6px}.area-image *{pointer-events:none}.new-image-dialog .area-image .has-image{position:relative;width:100%;height:100%}.new-image-dialog .area-image .has-image .remove{position:absolute;top:.5em;left:.5em}.new-image-dialog .area-settings{grid-area:settings}.new-image-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.new-image-dialog .area-buttons{align-self:end;grid-area:buttons}.new-image-dialog .area-buttons button{width:100%;margin-top:.5em}.new-image-dialog .upload{position:absolute;top:0;left:0;right:0;bottom:0;cursor:pointer}.new-image-dialog .upload .btn{position:absolute;top:50%;transform:translate(-50%,-50%)}.edit-image-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}.edit-image-dialog .area-image{grid-area:image;margin:20px}.edit-image-dialog .area-image.no-image{align-content:center;display:grid;text-align:center;border:dashed 6px;position:relative}.edit-image-dialog .area-image .has-image{position:relative;width:100%;height:100%}.edit-image-dialog .area-image .has-image .remove{position:absolute;top:.5em;left:.5em}.edit-image-dialog .area-settings{grid-area:settings}.edit-image-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.edit-image-dialog .area-buttons{align-self:end;grid-area:buttons}.edit-image-dialog .area-buttons button{width:100%;margin-top:.5em}.new-game-dialog .overlay-content{display:grid;grid-template-columns:auto 450px;grid-template-rows:auto;grid-template-areas:"image settings" "image buttons";height:90%;width:80%}@media (max-width:1400px){.new-game-dialog .overlay-content{grid-template-columns:auto;grid-template-rows:1fr min-content min-content;grid-template-areas:"image" "settings" "buttons"}}.new-game-dialog .area-image{grid-area:image;margin:20px}.new-game-dialog .area-settings{grid-area:settings}.new-game-dialog .area-settings table input[type=text]{width:100%;box-sizing:border-box}.new-game-dialog .area-buttons{align-self:end;grid-area:buttons}.new-game-dialog .area-buttons button{width:100%}.new-game-dialog .has-image{position:relative;width:100%;height:100%}.new-game-dialog .has-image .remove{position:absolute;top:.5em;left:.5em} \ No newline at end of file diff --git a/build/public/assets/index.bc3449de.js b/build/public/assets/index.bc3449de.js new file mode 100644 index 0000000..adfd154 --- /dev/null +++ b/build/public/assets/index.bc3449de.js @@ -0,0 +1 @@ +import{d as e,c as t,a as n,w as o,b as l,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 x,s as C,u as k,x as A,y as S}from"./vendor.684f7bc8.js";var z=e({name:"app",computed:{showNav(){return!["game","replay"].includes(String(this.$route.name))}}});const T={id:"app"},P={key:0,class:"nav"},I=s("Index"),D=s("New game");z.render=function(e,s,r,d,c,u){const p=a("router-link"),g=a("router-view");return i(),t("div",T,[e.showNav?(i(),t("ul",P,[n("li",null,[n(p,{class:"btn",to:{name:"index"}},{default:o((()=>[I])),_:1})]),n("li",null,[n(p,{class:"btn",to:{name:"new-game"}},{default:o((()=>[D])),_:1})])])):l("",!0),n(g)])};const E=864e5,_=e=>{const t=Math.floor(e/E);e%=E;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 M=1e3,O=()=>{const e=new Date;return Date.UTC(e.getUTCFullYear(),e.getUTCMonth(),e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),e.getUTCMilliseconds())},N=(e,t)=>_(t-e),B=_,U=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,l=t||O();return`${n} ${N(o,l)}`}}});const R={class:"game-info-text"},V=n("br",null,null,-1),$=n("br",null,null,-1),G=n("br",null,null,-1),F=s(" β†ͺ️ Watch replay ");U.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:o((()=>[n("span",R,[s(" 🧩 "+r(e.game.tilesFinished)+"/"+r(e.game.tilesTotal),1),V,s(" πŸ‘₯ "+r(e.game.players),1),$,s(" "+r(e.time(e.game.started,e.game.finished)),1),G])])),_:1},8,["to"]),e.game.hasReplay?(i(),t(h,{key:0,class:"game-replay",to:{name:"replay",params:{id:e.game.id}}},{default:o((()=>[F])),_:1},8,["to"])):l("",!0)],4)};var L=e({components:{GameTeaser:U},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 j=n("h1",null,"Running games",-1),W=n("h1",null,"Finished games",-1);L.render=function(e,o,l,s,r,u){const p=a("game-teaser");return i(),t("div",null,[j,(i(!0),t(d,null,c(e.gamesRunning,((e,o)=>(i(),t("div",{class:"game-teaser-wrap",key:o},[n(p,{game:e},null,8,["game"])])))),128)),W,(i(!0),t(d,null,c(e.gamesFinished,((e,o)=>(i(),t("div",{class:"game-teaser-wrap",key:o},[n(p,{game:e},null,8,["game"])])))),128))])};var q=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")}}});q.render=function(e,o,l,a,s,r){return i(),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 H,Y,Q,Z,K,X,J,ee,te=e({name:"image-library",components:{ImageTeaser:q},props:{images:{type:Array,required:!0}},emits:{imageClicked:null,imageEditClicked:null},methods:{imageClicked(e){this.$emit("imageClicked",e)},imageEditClicked(e){this.$emit("imageEditClicked",e)}}});te.render=function(e,n,o,l,s,r){const u=a("image-teaser");return i(),t("div",null,[(i(!0),t(d,null,c(e.images,((n,o)=>(i(),t(u,{image:n,onClick:t=>e.imageClicked(n),onEditClick:t=>e.imageEditClicked(n),key:o},null,8,["image","onClick","onEditClick"])))),128))])},(Y=H||(H={}))[Y.Flat=0]="Flat",Y[Y.Out=1]="Out",Y[Y.In=-1]="In",(Z=Q||(Q={}))[Z.FINAL=0]="FINAL",Z[Z.ANY=1]="ANY",(X=K||(K={}))[X.NORMAL=0]="NORMAL",X[X.ANY=1]="ANY",X[X.FLAT=2]="FLAT",(ee=J||(J={}))[ee.NORMAL=0]="NORMAL",ee[ee.REAL=1]="REAL";class ne{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 ne(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},le=(...e)=>{const t=t=>(...n)=>{const o=new Date,l=oe(o.getHours(),"00"),a=oe(o.getMinutes(),"00"),i=oe(o.getSeconds(),"00");console[t](`${l}:${a}:${i}`,...e,...n)};return{log:t("log"),error:t("error"),info:t("info")}};var ae={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||"",ne.serialize(e.rng.obj),e.puzzle,e.players,e.evtInfos,e.scoreMode||Q.FINAL,e.shapeMode||K.ANY,e.snapMode||J.NORMAL]},decodeGame:function(e){return{id:e[0],rng:{type:e[1],obj:ne.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 o=[n,e[n]].map(encodeURIComponent);t.push(o.join("="))}return 0===t.length?"":`?${t.join("&")}`}};const ie={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}}}};ie.render=function(e,n,o,l,a,s){return i(),t("div",{style:s.style,title:o.title},null,12,["title"])};var se=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.idx0?(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 re=m();y("data-v-39ed99c7");const de={key:0,class:"autocomplete"};f();const ce=re(((e,o,a,s,u,m)=>(i(),t("div",null,[p(n("input",{ref:"input",class:"input",type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.input=t),placeholder:"Plants, People",onChange:o[2]||(o[2]=(...t)=>e.onChange&&e.onChange(...t)),onKeydown:o[3]||(o[3]=h(((...t)=>e.add&&e.add(...t)),["enter"])),onKeyup:o[4]||(o[4]=(...t)=>e.onKeyUp&&e.onKeyUp(...t))},null,544),[[g,e.input]]),e.autocomplete.values?(i(),t("div",de,[n("ul",null,[(i(!0),t(d,null,c(e.autocomplete.values,((n,o)=>(i(),t("li",{key:o,class:{active:o===e.autocomplete.idx},onClick:t=>e.addVal(n)},r(n),11,["onClick"])))),128))])])):l("",!0),(i(!0),t(d,null,c(e.values,((n,o)=>(i(),t("span",{key:o,class:"bit",onClick:t=>e.rm(n)},r(n)+" βœ–",9,["onClick"])))),128))]))));se.render=ce,se.__scopeId="data-v-39ed99c7";const ue=le("NewImageDialog.vue");var pe=e({name:"new-image-dialog",components:{ResponsiveImage:ie,TagsInput:se},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 o=n[0];return o.type.startsWith("image/")?o: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(){ue.info("onDragleave"),this.droppable=!1}}});const ge={key:0,class:"has-image"},he={key:1},me={class:"upload"},ye=n("span",{class:"btn"},"Upload File",-1),fe={class:"area-settings"},ve=n("td",null,[n("label",null,"Title")],-1),we=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),be=n("td",null,[n("label",null,"Tags")],-1),xe={class:"area-buttons"},Ce=s("🧩 Post to gallery "),ke=n("br",null,null,-1),Ae=s(" + set up game");pe.render=function(e,o,l,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),t("div",{class:"overlay new-image-dialog",onClick:o[11]||(o[11]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[10]||(o[10]=u((()=>{}),["stop"]))},[n("div",{class:["area-image",{"has-image":!!e.previewUrl,"no-image":!e.previewUrl,droppable:e.droppable}],onDrop:o[3]||(o[3]=(...t)=>e.onDrop&&e.onDrop(...t)),onDragover:o[4]||(o[4]=(...t)=>e.onDragover&&e.onDragover(...t)),onDragleave:o[5]||(o[5]=(...t)=>e.onDragleave&&e.onDragleave(...t))},[e.previewUrl?(i(),t("div",ge,[n("span",{class:"remove btn",onClick:o[1]||(o[1]=t=>e.previewUrl="")},"X"),n(c,{src:e.previewUrl},null,8,["src"])])):(i(),t("div",he,[n("label",me,[n("input",{type:"file",style:{display:"none"},onChange:o[2]||(o[2]=(...t)=>e.onFileSelect&&e.onFileSelect(...t)),accept:"image/*"},null,32),ye])]))],34),n("div",fe,[n("table",null,[n("tr",null,[ve,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[6]||(o[6]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),we,n("tr",null,[be,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[7]||(o[7]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",xe,[n("button",{class:"btn",disabled:!e.canPostToGallery,onClick:o[8]||(o[8]=(...t)=>e.postToGallery&&e.postToGallery(...t))},"πŸ–ΌοΈ Post to gallery",8,["disabled"]),n("button",{class:"btn",disabled:!e.canSetupGameClick,onClick:o[9]||(o[9]=(...t)=>e.setupGameClick&&e.setupGameClick(...t))},[Ce,ke,Ae],8,["disabled"])])])])};var Se=e({name:"edit-image-dialog",components:{ResponsiveImage:ie,TagsInput:se},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"},Te={class:"has-image"},Pe={class:"area-settings"},Ie=n("td",null,[n("label",null,"Title")],-1),De=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),Ee=n("td",null,[n("label",null,"Tags")],-1),_e={class:"area-buttons"};Se.render=function(e,o,l,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),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",ze,[n("div",Te,[n(c,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",Pe,[n("table",null,[n("tr",null,[Ie,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),De,n("tr",null,[Ee,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[2]||(o[2]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",_e,[n("button",{class:"btn",onClick:o[3]||(o[3]=(...t)=>e.saveImage&&e.saveImage(...t))},"πŸ–ΌοΈ Save image")])])])};var Me=e({name:"new-game-dialog",components:{ResponsiveImage:ie},props:{image:{type:Object,required:!0}},emits:{newGame:null,bgclick:null},data:()=>({tiles:1e3,scoreMode:Q.ANY,shapeMode:K.NORMAL,snapMode:J.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 Oe={class:"area-image"},Ne={class:"has-image"},Be={class:"area-settings"},Ue=n("td",null,[n("label",null,"Pieces")],-1),Re=n("td",null,[n("label",null,"Scoring: ")],-1),Ve=s(" Any (Score when pieces are connected to each other or on final location)"),$e=n("br",null,null,-1),Ge=s(" Final (Score when pieces are put to their final location)"),Fe=n("td",null,[n("label",null,"Shapes: ")],-1),Le=s(" Normal"),je=n("br",null,null,-1),We=s(" Any (flat pieces can occur anywhere)"),qe=n("br",null,null,-1),He=s(" Flat (all pieces flat on all sides)"),Ye=n("td",null,[n("label",null,"Snapping: ")],-1),Qe=s(" Normal (pieces snap to final destination and to each other)"),Ze=n("br",null,null,-1),Ke=s(" Real (pieces snap only to corners, already snapped pieces and to each other)"),Xe={class:"area-buttons"};Me.render=function(e,o,l,s,r,d){const c=a("responsive-image");return i(),t("div",{class:"overlay new-game-dialog",onClick:o[11]||(o[11]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[10]||(o[10]=u((()=>{}),["stop"]))},[n("div",Oe,[n("div",Ne,[n(c,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",Be,[n("table",null,[n("tr",null,[Ue,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.tiles=t)},null,512),[[g,e.tiles]])])]),n("tr",null,[Re,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[2]||(o[2]=t=>e.scoreMode=t),value:"1"},null,512),[[v,e.scoreMode]]),Ve]),$e,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[3]||(o[3]=t=>e.scoreMode=t),value:"0"},null,512),[[v,e.scoreMode]]),Ge])])]),n("tr",null,[Fe,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[4]||(o[4]=t=>e.shapeMode=t),value:"0"},null,512),[[v,e.shapeMode]]),Le]),je,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[5]||(o[5]=t=>e.shapeMode=t),value:"1"},null,512),[[v,e.shapeMode]]),We]),qe,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[6]||(o[6]=t=>e.shapeMode=t),value:"2"},null,512),[[v,e.shapeMode]]),He])])]),n("tr",null,[Ye,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[7]||(o[7]=t=>e.snapMode=t),value:"0"},null,512),[[v,e.snapMode]]),Qe]),Ze,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[8]||(o[8]=t=>e.snapMode=t),value:"1"},null,512),[[v,e.snapMode]]),Ke])])])])]),n("div",Xe,[n("button",{class:"btn",disabled:!e.canStartNewGame,onClick:o[9]||(o[9]=(...t)=>e.onNewGameClick&&e.onNewGameClick(...t))}," 🧩 Generate Puzzle ",8,["disabled"])])])])};var Je=e({components:{ImageLibrary:te,NewImageDialog:pe,EditImageDialog:Se,NewGameDialog:Me},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${ae.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 et={class:"upload-image-teaser"},tt=n("div",{class:"hint"},"(The image you upload will be added to the public gallery.)",-1),nt={key:0},ot=s(" Tags: "),lt=s(" Sort by: "),at=n("option",{value:"date_desc"},"Newest first",-1),it=n("option",{value:"date_asc"},"Oldest first",-1),st=n("option",{value:"alpha_asc"},"A-Z",-1),rt=n("option",{value:"alpha_desc"},"Z-A",-1);Je.render=function(e,o,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",et,[n("div",{class:"btn btn-big",onClick:o[1]||(o[1]=t=>e.dialog="new-image")},"Upload your image"),tt]),n("div",null,[e.tags.length>0?(i(),t("label",nt,[ot,(i(!0),t(d,null,c(e.relevantTags,((n,o)=>(i(),t("span",{class:["bit",{on:e.filters.tags.includes(n.slug)}],key:o,onClick:t=>e.toggleTag(n)},r(n.title)+" ("+r(n.total)+")",11,["onClick"])))),128))])):l("",!0),n("label",null,[lt,p(n("select",{"onUpdate:modelValue":o[2]||(o[2]=t=>e.filters.sort=t),onChange:o[3]||(o[3]=(...t)=>e.filtersChanged&&e.filtersChanged(...t))},[at,it,st,rt],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:o[4]||(o[4]=t=>e.dialog=""),onPostToGalleryClick:e.postToGalleryClick,onSetupGameClick:e.setupGameClick},null,8,["autocompleteTags","onPostToGalleryClick","onSetupGameClick"])):l("",!0),"edit-image"===e.dialog?(i(),t(f,{key:1,autocompleteTags:e.autocompleteTags,onBgclick:o[5]||(o[5]=t=>e.dialog=""),onSaveClick:e.onSaveImageClick,image:e.image},null,8,["autocompleteTags","onSaveClick","image"])):l("",!0),e.image&&"new-game"===e.dialog?(i(),t(v,{key:2,onBgclick:o[6]||(o[6]=t=>e.dialog=""),onNewGame:e.onNewGame,image:e.image},null,8,["onNewGame","image"])):l("",!0)])};var dt=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 ct={class:"scores"},ut=n("div",null,"Scores",-1),pt=n("td",null,"⚑",-1),gt=n("td",null,"πŸ’€",-1);dt.render=function(e,o,l,a,s,u){return i(),t("div",ct,[ut,n("table",null,[(i(!0),t(d,null,c(e.actives,((e,o)=>(i(),t("tr",{key:o,style:{color:e.color}},[pt,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,o)=>(i(),t("tr",{key:o,style:{color:e.color}},[gt,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128))])])};var ht=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 B(this.duration)}}});const mt={class:"timer"};ht.render=function(e,o,l,a,s,d){return i(),t("div",mt,[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 yt=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 ft=n("td",null,[n("label",null,"Background: ")],-1),vt=n("td",null,[n("label",null,"Color: ")],-1),wt=n("td",null,[n("label",null,"Name: ")],-1),bt=n("td",null,[n("label",null,"Sounds: ")],-1);yt.render=function(e,o,l,a,s,r){return i(),t("div",{class:"overlay transparent",onClick:o[6]||(o[6]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content settings",onClick:o[5]||(o[5]=u((()=>{}),["stop"]))},[n("tr",null,[ft,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":o[1]||(o[1]=t=>e.modelValue.background=t)},null,512),[[g,e.modelValue.background]])])]),n("tr",null,[vt,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":o[2]||(o[2]=t=>e.modelValue.color=t)},null,512),[[g,e.modelValue.color]])])]),n("tr",null,[wt,n("td",null,[p(n("input",{type:"text",maxLength:"16","onUpdate:modelValue":o[3]||(o[3]=t=>e.modelValue.name=t)},null,512),[[g,e.modelValue.name]])])]),n("tr",null,[bt,n("td",null,[p(n("input",{type:"checkbox","onUpdate:modelValue":o[4]||(o[4]=t=>e.modelValue.soundsEnabled=t)},null,512),[[x,e.modelValue.soundsEnabled]])])])])])};var xt=e({name:"preview-overlay",props:{img:String},emits:{bgclick:null},computed:{previewStyle(){return{backgroundImage:`url('${this.img}')`}}}});const Ct={class:"preview"};xt.render=function(e,o,l,a,s,r){return i(),t("div",{class:"overlay",onClick:o[1]||(o[1]=t=>e.$emit("bgclick"))},[n("div",Ct,[n("div",{class:"img",style:e.previewStyle},null,4)])])};var kt=1,At=4,St=2,zt=3,Tt=2,Pt=4,It=3,Dt=9,Et=1,_t=2,Mt=3,Ot=4,Nt=5,Bt=6,Ut=7,Rt=8,Vt=10,$t=11,Gt=1,Ft=2,Lt=3;const jt=le("Communication.js");let Wt,qt=[],Ht=e=>{qt.push(e)},Yt=[],Qt=e=>{Yt.push(e)};let Zt=0;const Kt=e=>{Zt!==e&&(Zt=e,Qt(e))};function Xt(e){if(2===Zt)try{Wt.send(JSON.stringify(e))}catch(t){jt.info("unable to send message.. maybe because ws is invalid?")}}let Jt,en;var tn={connect:function(e,t,n){return Jt=0,en={},Kt(3),new Promise((o=>{Wt=new WebSocket(e,n+"|"+t),Wt.onopen=()=>{Kt(2),Xt([zt])},Wt.onmessage=e=>{const t=JSON.parse(e.data),l=t[0];if(l===At){const e=t[1];o(e)}else{if(l!==kt)throw`[ 2021-05-09 invalid connect msgType ${l} ]`;{const e=t[1],o=t[2];if(e===n&&en[o])return void delete en[o];Ht(t)}}},Wt.onerror=()=>{throw Kt(1),"[ 2021-05-15 onerror ]"},Wt.onclose=e=>{4e3===e.code||1001===e.code?Kt(4):Kt(1)}}))},requestReplayData:async function(e,t,n){const o={gameId:e,offset:t,size:n},l=await fetch(`/api/replay-data${ae.asQueryArgs(o)}`);return await l.json()},disconnect:function(){Wt&&Wt.close(4e3),Jt=0,en={}},sendClientEvent:function(e){Jt++,en[Jt]=e,Xt([St,Jt,en[Jt]])},onServerChange:function(e){Ht=e;for(const t of qt)Ht(t);qt=[]},onConnectionStateChange:function(e){Qt=e;for(const t of Yt)Qt(t);Yt=[]},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},nn=e({name:"connection-overlay",emits:{reconnect:null},props:{connectionState:Number},computed:{lostConnection(){return this.connectionState===tn.CONN_STATE_DISCONNECTED},connecting(){return this.connectionState===tn.CONN_STATE_CONNECTING},show(){return!(!this.lostConnection&&!this.connecting)}}});const on={key:0,class:"overlay connection-lost"},ln={key:0,class:"overlay-content"},an=n("div",null,"⁉️ LOST CONNECTION ⁉️",-1),sn={key:1,class:"overlay-content"},rn=n("div",null,"Connecting...",-1);nn.render=function(e,o,a,s,r,d){return e.show?(i(),t("div",on,[e.lostConnection?(i(),t("div",ln,[an,n("span",{class:"btn",onClick:o[1]||(o[1]=t=>e.$emit("reconnect"))},"Reconnect")])):l("",!0),e.connecting?(i(),t("div",sn,[rn])):l("",!0)])):l("",!0)};var dn=e({name:"help-overlay",emits:{bgclick:null}});const cn=n("tr",null,[n("td",null,"⬆️ Move up:"),n("td",null,[n("div",null,[n("kbd",null,"W"),s("/"),n("kbd",null,"↑"),s("/πŸ–±οΈ")])])],-1),un=n("tr",null,[n("td",null,"⬇️ Move down:"),n("td",null,[n("div",null,[n("kbd",null,"S"),s("/"),n("kbd",null,"↓"),s("/πŸ–±οΈ")])])],-1),pn=n("tr",null,[n("td",null,"⬅️ Move left:"),n("td",null,[n("div",null,[n("kbd",null,"A"),s("/"),n("kbd",null,"←"),s("/πŸ–±οΈ")])])],-1),gn=n("tr",null,[n("td",null,"➑️ Move right:"),n("td",null,[n("div",null,[n("kbd",null,"D"),s("/"),n("kbd",null,"β†’"),s("/πŸ–±οΈ")])])],-1),hn=n("tr",null,[n("td"),n("td",null,[n("div",null,[s("Move faster by holding "),n("kbd",null,"Shift")])])],-1),mn=n("tr",null,[n("td",null,"πŸ”+ Zoom in:"),n("td",null,[n("div",null,[n("kbd",null,"E"),s("/πŸ–±οΈ-Wheel")])])],-1),yn=n("tr",null,[n("td",null,"πŸ”- Zoom out:"),n("td",null,[n("div",null,[n("kbd",null,"Q"),s("/πŸ–±οΈ-Wheel")])])],-1),fn=n("tr",null,[n("td",null,"πŸ–ΌοΈ Toggle preview:"),n("td",null,[n("div",null,[n("kbd",null,"Space")])])],-1),vn=n("tr",null,[n("td",null,"πŸ§©βœ”οΈ Toggle fixed pieces:"),n("td",null,[n("div",null,[n("kbd",null,"F")])])],-1),wn=n("tr",null,[n("td",null,"πŸ§©β“ Toggle loose pieces:"),n("td",null,[n("div",null,[n("kbd",null,"G")])])],-1),bn=n("tr",null,[n("td",null,"πŸ”‰ Toggle sounds:"),n("td",null,[n("div",null,[n("kbd",null,"M")])])],-1);dn.render=function(e,o,l,a,s,r){return i(),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"]))},[cn,un,pn,gn,hn,mn,yn,fn,vn,wn,bn])])};var xn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"/assets/click.bb97cb07.mp3"}),Cn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAW0lEQVQ4je1RywrAIAxLxP//5exixRWlVgZelpOKeTQFfnDypgy3eLIkSLLL8mxGPoHsU2hPAgDHBLvRX6hZZw/fwT0BtlLSONqCbWAmEIqMZOCDDlaDR3N03gOyDCn+y4DWmAAAAABJRU5ErkJggg=="}),kn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARElEQVQ4jWNgGAU0Af+hmBCbgYGBgYERhwHEAEYGBgYGJtIdiApYyLAZBVDsAqoagC1ACQJyY4ERg0GCISh6KA4DigEAou8LC+LnIJoAAAAASUVORK5CYII="}),An=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVQ4ja1TQQ7AIAgD///n7jCozA2Hbk00jbG1KIrcARszTugoBs49qioZj7r2kKACptkyAOCJsJuA+GzglwHjvMSSWFVaENWVASxh5eRLiq5fN/ASjI89VcP2K3hHpq1cEXNaMfnrL3TDZP2tDuoOA6MzCCXWr38AAAAASUVORK5CYII="}),Sn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAU0lEQVQ4jWNgoAH4D8X42HDARKlt5BoAd82AuQAOGLGIYQQUPv0wF5CiCQUge4EsQ5C9QI4BjMguwBYeBAElscCIy1ZivMKIwSDBEBQ9FCckigEAU3QOD7TGvY4AAAAASUVORK5CYII="});function zn(){let e=0,t=0,n=1;const o=(o,l)=>{e+=o/n,t+=l/n},l=e=>{const t=n+.05*n*("in"===e?1:-1);return Math.min(Math.max(t,.1),6)},a=o=>({x:o.x/n-e,y:o.y/n-t}),i=o=>({x:(o.x+e)*n,y:(o.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:o,canZoom:e=>n!=l(e),zoom:(e,t)=>((e,t)=>{if(n==e)return!1;const l=1-n/e;return o(-t.x*l,-t.y*l),n=e,!0})(l(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 Tn(e=0,t=0){const n=document.createElement("canvas");return n.width=e,n.height=t,n}var Pn={createCanvas:Tn,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=Tn(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=Tn(e.width,e.height),l=o.getContext("2d");return l.save(),l.drawImage(t,0,0),l.fillStyle=n,l.globalCompositeOperation="source-in",l.fillRect(0,0,t.width,t.height),l.restore(),l.save(),l.globalCompositeOperation="destination-over",l.drawImage(e,0,0),l.restore(),o}};const In=le("Debug.js");let Dn=0,En=0;var _n=e=>{Dn=performance.now(),En=e},Mn=e=>{const t=performance.now(),n=t-Dn;n>En&&In.log(e+": "+n),Dn=t};function On(e,t){const n=e.x-t.x,o=e.y-t.y;return Math.sqrt(n*n+o*o)}function Nn(e){return{x:e.x+e.w/2,y:e.y+e.h/2}}var Bn={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:On,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:Nn,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 On(Nn(e),Nn(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=le("PuzzleGraphics.js");function Rn(e,t){const n=ae.coordByPieceIdx(e,t);return{x:n.x*e.tileSize,y:n.y*e.tileSize,w:e.tileSize,h:e.tileSize}}var Vn={loadPuzzleBitmaps:async function(e){const t=await Pn.loadImageToBitmap(e.info.imageUrl),n=await Pn.resizeBitmap(t,e.info.width,e.info.height);return await async function(e,t,n){Un.log("start createPuzzleTileBitmaps");const o=n.tileSize,l=n.tileMarginWidth,a=n.tileDrawSize,i=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),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:l,y:l},r=Bn.pointAdd(a,{x:o,y:0}),c=Bn.pointAdd(r,{x:0,y:o}),u=Bn.pointSub(c,{x:o,y:0});if(n.moveTo(a.x,a.y),0!==e.top)for(let o=0;oae.decodePiece($n[e].puzzle.tiles[t]),eo=(e,t)=>Jn(e,t).group,to=(e,t)=>{const n=$n[e].puzzle.info;return 0===t||t===n.tilesX-1||t===n.tiles-n.tilesX||t===n.tiles-1},no=(e,t)=>{const n=$n[e].puzzle.info,o={x:(n.table.width-n.width)/2,y:(n.table.height-n.height)/2},l=function(e,t){const n=$n[e].puzzle.info,o=ae.coordByPieceIdx(n,t),l=o.x*n.tileSize,a=o.y*n.tileSize;return{x:l,y:a}}(e,t);return Bn.pointAdd(o,l)},oo=(e,t)=>Jn(e,t).pos,lo=e=>{const t=Co(e),n=ko(e),o=Math.round(t/4),l=Math.round(n/4);return{x:0-o,y:0-l,w:t+2*o,h:n+2*l}},ao=(e,t)=>{const n=co(e),o=Jn(e,t);return{x:o.pos.x,y:o.pos.y,w:n,h:n}},io=(e,t)=>Jn(e,t).z,so=(e,t)=>{for(const n of $n[e].puzzle.tiles){const e=ae.decodePiece(n);if(e.owner===t)return e.idx}return-1},ro=e=>$n[e].puzzle.info.tileDrawSize,co=e=>$n[e].puzzle.info.tileSize,uo=e=>$n[e].puzzle.data.maxGroup,po=e=>$n[e].puzzle.data.maxZ;function go(e,t){const n=$n[e].puzzle.info,o=ae.coordByPieceIdx(n,t);return[o.y>0?t-n.tilesX:-1,o.x0?t-1:-1]}const ho=(e,t,n)=>{for(const o of t)Xn(e,o,{z:n})},mo=(e,t,n)=>{const o=oo(e,t);Xn(e,t,{pos:Bn.pointAdd(o,n)})},yo=(e,t,n)=>{const o=ro(e),l=lo(e),a=n;for(const i of t){const t=Jn(e,i);t.pos.x+n.xl.x+l.w&&(a.x=Math.min(l.x+l.w-t.pos.x+o,a.x)),t.pos.y+n.yl.y+l.h&&(a.y=Math.min(l.y+l.h-t.pos.y+o,a.y))}for(const i of t)mo(e,i,a)},fo=(e,t)=>Jn(e,t).owner,vo=(e,t)=>{for(const n of t)Xn(e,n,{owner:-1,z:1})},wo=(e,t,n)=>{for(const o of t)Xn(e,o,{owner:n})};function bo(e,t){const n=$n[e].puzzle.tiles,o=ae.decodePiece(n[t]),l=[];if(o.group)for(const a of n){const e=ae.decodePiece(a);e.group===o.group&&l.push(e.idx)}else l.push(o.idx);return l}const xo=(e,t)=>{const n=Fn(e,t);return n?n.points:0},Co=e=>$n[e].puzzle.info.table.width,ko=e=>$n[e].puzzle.info.table.height;var Ao={setGame:function(e,t){$n[e]=t},exists:function(e){return!!$n[e]||!1},playerExists:jn,getActivePlayers:function(e,t){const n=t-30*M;return Wn(e).filter((e=>e.ts>=n))},getIdlePlayers:function(e,t){const n=t-30*M;return Wn(e).filter((e=>e.ts0))},addPlayer:function(e,t,n){jn(e,t)?Zn(e,t,{ts:n}):Ln(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:Qn,getPieceCount:qn,getImageUrl:function(e){return $n[e].puzzle.info.imageUrl},setImageUrl:function(e,t){$n[e].puzzle.info.imageUrl=t},get:function(e){return $n[e]||null},getAllGames:function(){return Object.values($n).sort(((e,t)=>Yn(e.id)===Yn(t.id)?t.puzzle.data.started-e.puzzle.data.started:Yn(e.id)?1:-1))},getPlayerBgColor:(e,t)=>{const n=Fn(e,t);return n?n.bgcolor:null},getPlayerColor:(e,t)=>{const n=Fn(e,t);return n?n.color:null},getPlayerName:(e,t)=>{const n=Fn(e,t);return n?n.name:null},getPlayerIndexById:Gn,getPlayerIdByIndex:function(e,t){return $n[e].players.length>t?ae.decodePlayer($n[e].players[t]).id:null},changePlayer:Zn,setPlayer:Ln,setPiece:function(e,t,n){$n[e].puzzle.tiles[t]=ae.encodePiece(n)},setPuzzleData:function(e,t){$n[e].puzzle.data=t},getTableWidth:Co,getTableHeight:ko,getPuzzle:e=>$n[e].puzzle,getRng:e=>$n[e].rng.obj,getPuzzleWidth:e=>$n[e].puzzle.info.width,getPuzzleHeight:e=>$n[e].puzzle.info.height,getPiecesSortedByZIndex:function(e){return $n[e].puzzle.tiles.map(ae.decodePiece).sort(((e,t)=>e.z-t.z))},getFirstOwnedPiece:(e,t)=>{const n=so(e,t);return n<0?null:$n[e].puzzle.tiles[n]},getPieceDrawOffset:e=>$n[e].puzzle.info.tileDrawOffset,getPieceDrawSize:ro,getFinalPiecePos:no,getStartTs:e=>$n[e].puzzle.data.started,getFinishTs:e=>$n[e].puzzle.data.finished,handleInput:function(e,t,n,o,l){const a=$n[e].puzzle,i=function(e,t){return t in $n[e].evtInfos?$n[e].evtInfos[t]:{_last_mouse:null,_last_mouse_down:null}}(e,t),s=[],r=()=>{s.push([Gt,a.data])},d=t=>{s.push([Ft,ae.encodePiece(Jn(e,t))])},c=e=>{for(const t of e)d(t)},u=()=>{const n=Fn(e,t);n&&s.push([Lt,ae.encodePlayer(n)])},p=n[0];if(p===Bt){const l=n[1];Zn(e,t,{bgcolor:l,ts:o}),u()}else if(p===Ut){const l=n[1];Zn(e,t,{color:l,ts:o}),u()}else if(p===Rt){const l=`${n[1]}`.substr(0,16);Zn(e,t,{name:l,ts:o}),u()}else if(p===Dt){const l=n[1],a=n[2],i=Fn(e,t);if(i){const n=i.x-l,s=i.y-a;Zn(e,t,{ts:o,x:n,y:s}),u()}}else if(p===Et){const l={x:n[1],y:n[2]};Zn(e,t,{d:1,ts:o}),u(),i._last_mouse_down=l;const a=((e,t)=>{const n=$n[e].puzzle.info,o=$n[e].puzzle.tiles;let l=-1,a=-1;for(let i=0;il)&&(l=e.z,a=i)}return a})(e,l);if(a>=0){const n=po(e)+1;Kn(e,{maxZ:n}),r();const o=bo(e,a);ho(e,o,po(e)),wo(e,o,t),c(o)}i._last_mouse=l}else if(p===Mt){const l=n[1],a=n[2],s={x:l,y:a};if(null===i._last_mouse_down)Zn(e,t,{x:l,y:a,ts:o}),u();else{const n=so(e,t);if(n>=0){Zn(e,t,{x:l,y:a,ts:o}),u();const r=bo(e,n);let d=Bn.pointInBounds(s,lo(e))&&Bn.pointInBounds(i._last_mouse_down,lo(e));for(const t of r){const n=ao(e,t);if(Bn.pointInBounds(s,n)){d=!0;break}}if(d){const t=l-i._last_mouse_down.x,n=a-i._last_mouse_down.y;yo(e,r,{x:t,y:n}),c(r)}}else Zn(e,t,{ts:o}),u();i._last_mouse_down=s}i._last_mouse=s}else if(p===_t){const s={x:n[1],y:n[2]},p=0;i._last_mouse_down=null;const g=so(e,t);if(g>=0){const n=bo(e,g);wo(e,n,0),c(n);const i=oo(e,g),s=no(e,g);let h=!1;if(function(e){return $n[e].snapMode||J.NORMAL}(e)===J.REAL){for(const t of n)if(to(e,t)){h=!0;break}}else h=!0;if(h&&Bn.pointDistance(s,i){const l=$n[e].puzzle.info;if(n<0)return!1;if(((e,t,n)=>{const o=eo(e,t),l=eo(e,n);return!(!o||o!==l)})(e,t,n))return!1;const a=oo(e,t),i=Bn.pointAdd(oo(e,n),{x:o[0]*l.tileSize,y:o[1]*l.tileSize});if(Bn.pointDistance(a,i){const o=$n[e].puzzle.tiles,l=eo(e,t),a=eo(e,n);let i;const s=[];l&&s.push(l),a&&s.push(a),l?i=l:a?i=a:(Kn(e,{maxGroup:uo(e)+1}),r(),i=uo(e));if(Xn(e,t,{group:i}),d(t),Xn(e,n,{group:i}),d(n),s.length>0)for(const r of o){const t=ae.decodePiece(r);s.includes(t.group)&&(Xn(e,t.idx,{group:i}),d(t.idx))}})(e,t,n),l=bo(e,t),((e,t)=>-1===fo(e,t))(e,n))vo(e,l);else{const t=((e,t)=>{let n=0;for(const o of t){const t=io(e,o);t>n&&(n=t)}return n})(e,l);ho(e,l,t)}return c(l),!0}return!1};let a=!1;for(const t of bo(e,g)){const o=go(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])){a=!0;break}}if(a&&Hn(e)===Q.ANY){const n=xo(e,t)+1;Zn(e,t,{d:p,ts:o,points:n}),u()}else Zn(e,t,{d:p,ts:o}),u();a&&l&&l(t)}}else Zn(e,t,{d:p,ts:o}),u();i._last_mouse=s}else if(p===Ot){const l=n[1],a=n[2];Zn(e,t,{x:l,y:a,ts:o}),u(),i._last_mouse={x:l,y:a}}else if(p===Nt){const l=n[1],a=n[2];Zn(e,t,{x:l,y:a,ts:o}),u(),i._last_mouse={x:l,y:a}}else Zn(e,t,{ts:o}),u();return function(e,t,n){$n[e].evtInfos[t]=n}(e,t,i),s}};let So=-10,zo=20,To=2,Po=15;class Io{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=So+Math.random()*zo,this.vy=-1*(To+Math.random()*Po),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;To=t/2,Po=t-To;const n=1/4*this.canvas.width/(t/2);So=-n,zo=2*n}resize(){this.setSpeedParams()}init(){this.readyBombs=[],this.explodedBombs=[],this.particles=[];for(let e=0;e<1;e++)this.readyBombs.push(new Io(this.rng))}update(){100*Math.random()<5&&this.readyBombs.push(new Io(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(!y[t]){const n=e.d?r:d;if(e.color){const o=e.d?c:u;y[t]=await createImageBitmap(Pn.colorizedCanvas(n,o,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,Bo=!0})),t}(l,Pn.createCanvas()),w={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};tn.onConnectionStateChange((e=>{a.setConnectionState(e)}));const b=async e=>{w.requesting=!0;const t=await tn.requestReplayData(e,w.dataOffset,w.dataSize);return w.dataOffset+=w.dataSize,w.requesting=!1,t};let x=()=>0;const C=async()=>{if("play"===o){const o=await tn.connect(n,e,t),l=ae.decodeGame(o);Ao.setGame(l.id,l),x=()=>O()}else{if("replay"!==o)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=ae.decodeGame(t.game);Ao.setGame(n.id,n),w.requesting=!1,w.log=t.log,w.lastRealTs=O(),w.gameStartTs=parseInt(w.log[0][4],10),w.lastGameTs=w.gameStartTs,w.final=!1,w.logPointer=0,w.speeds=[.5,1,2,5,10,20,50,100,250,500],w.speedIdx=1,w.paused=!1,w.dataOffset=0,w.dataSize=1e4,x=()=>w.lastGameTs}}Bo=!0};await C();const k=Ao.getPieceDrawOffset(e),A=Ao.getPieceDrawSize(e),S=Ao.getPuzzleWidth(e),z=Ao.getPuzzleHeight(e),T=Ao.getTableWidth(e),P=Ao.getTableHeight(e),I={x:(T-S)/2,y:(P-z)/2},D={w:S,h:z},E={w:A,h:A},_=await Vn.loadPuzzleBitmaps(Ao.getPuzzle(e)),M=new Eo(v,Ao.getRng(e));M.init();const N=v.getContext("2d");v.classList.add("loaded");const B=zn();B.move(-(T-v.width)/2,-(P-v.height)/2);const U=function(e,t,n){let o=[],l=!0,a=!1,i=!1,s=!1,r=!1,d=!1,c=!1,u=!1;const p=(e,t)=>{const o=n.viewportToWorld({x:e,y:t});return[o.x,o.y]},g=e=>p(e.offsetX,e.offsetY),h=()=>p(e.width/2,e.height/2),m=(e,t)=>{l&&("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?a=e:"ArrowRight"===t.key||"d"===t.key||"D"===t.key?i=e:"q"===t.key?c=e:"e"===t.key&&(d=e))};let y=null;e.addEventListener("mousedown",(e=>{y=g(e),0===e.button&&f([Et,...y])})),e.addEventListener("mouseup",(e=>{y=g(e),0===e.button&&f([_t,...y])})),e.addEventListener("mousemove",(e=>{y=g(e),f([Mt,...y])})),e.addEventListener("wheel",(e=>{if(y=g(e),n.canZoom(e.deltaY<0?"in":"out")){const t=e.deltaY<0?Ot:Nt;f([t,...y])}})),t.addEventListener("keydown",(e=>m(!0,e))),t.addEventListener("keyup",(e=>m(!1,e))),t.addEventListener("keypress",(e=>{l&&(" "===e.key&&f([Vt]),"F"!==e.key&&"f"!==e.key||(Oo=!Oo,Bo=!0),"G"!==e.key&&"g"!==e.key||(No=!No,Bo=!0),"M"!==e.key&&"m"!==e.key||f([$t]))}));const f=e=>{o.push(e)};return{addEvent:f,consumeAll:()=>{if(0===o.length)return[];const e=o.slice();return o=[],e},createKeyEvents:()=>{const e=(a?1:0)-(i?1:0),t=(s?1:0)-(r?1:0);if(0!==e||0!==t){const o=(u?24:12)*Math.sqrt(n.getCurrentZoom()),l=n.viewportDimToWorld({w:e*o,h:t*o});f([Dt,l.w,l.h]),y&&(y[0]-=l.w,y[1]-=l.h)}if(d&&c);else if(d){if(n.canZoom("in")){const e=y||h();f([Ot,...e])}}else if(c&&n.canZoom("out")){const e=y||h();f([Nt,...e])}},setHotkeys:e=>{l=e}}}(v,window,B),R=Ao.getImageUrl(e),V=()=>{const t=Ao.getStartTs(e),n=Ao.getFinishTs(e),o=x();a.setFinished(!!n),a.setDuration((n||o)-t)};V(),a.setPiecesDone(Ao.getFinishedPiecesCount(e)),a.setPiecesTotal(Ao.getPieceCount(e));const $=x();a.setActivePlayers(Ao.getActivePlayers(e,$)),a.setIdlePlayers(Ao.getIdlePlayers(e,$));const G=!!Ao.getFinishTs(e);let F=G;const L=()=>F&&!G,j=()=>{const e=localStorage.getItem("sound_enabled");return null!==e&&"1"===e},W=()=>Ao.getPlayerBgColor(e,t)||localStorage.getItem("bg_color")||"#222222",q=()=>Ao.getPlayerColor(e,t)||localStorage.getItem("player_color")||"#ffffff";let H="",Y="",Q=!1;const Z=e=>{Q=e;const[t,n]=e?[H,"grab"]:[Y,"default"];v.style.cursor=`url('${t}') ${g} ${m}, ${n}`},K=e=>{H=Pn.colorizedCanvas(r,c,e).toDataURL(),Y=Pn.colorizedCanvas(d,u,e).toDataURL(),Z(Q)};K(q());const X=()=>{a.setReplaySpeed&&a.setReplaySpeed(w.speeds[w.speedIdx]),a.setReplayPaused&&a.setReplayPaused(w.paused)},J=[],ee=()=>{J.forEach((e=>{clearInterval(e)}))};let te;"play"===o?J.push(setInterval((()=>{V()}),1e3)):"replay"===o&&X(),"play"===o?tn.onServerChange((n=>{n[0],n[1],n[2];const o=n[3];for(const[l,a]of o)switch(l){case Lt:{const n=ae.decodePlayer(a);n.id!==t&&(Ao.setPlayer(e,n.id,n),Bo=!0)}break;case Ft:{const t=ae.decodePiece(a);Ao.setPiece(e,t.idx,t),Bo=!0}break;case Gt:Ao.setPuzzleData(e,a),Bo=!0}F=!!Ao.getFinishTs(e)})):"replay"===o&&J.push(setInterval((()=>{const t=O();if(w.requesting)return void(w.lastRealTs=t);if(w.logPointer+1>=w.log.length)return w.lastRealTs=t,void(async e=>{const t=await b(e);w.log=w.log.slice(w.logPointer),w.logPointer=0,w.log.push(...t.log),t.log.length=w.log.length){w.final&&ee();break}const n=w.log[t],l=w.gameStartTs+n[n.length-1];if(l>o)break;const a=n.slice();if(a[0]===Tt){const t=a[1];Ao.addPlayer(e,t,l),Bo=!0}else if(a[0]===Pt){const t=Ao.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (update player) ]";Ao.addPlayer(e,t,l),Bo=!0}else if(a[0]===It){const t=Ao.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (handle input) ]";const n=a[2];Ao.handleInput(e,t,n,l),Bo=!0}w.logPointer=t}w.lastRealTs=t,w.lastGameTs=o,V()}),50));let ne=null;return te=(e=>{let t=!1;const n=e.fps||60,o=e.slow||1,l=e.update,a=e.render,i=window.requestAnimationFrame,s=1/n,r=o*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,l(s);a(c/o),u=d,t||i(p)};return i(p),{stop:()=>{t=!0}}})({update:()=>{U.createKeyEvents();for(const n of U.consumeAll())if("play"===o){const o=n[0];if(o===Dt){const e=n[1],t=n[2],o=B.worldDimToViewport({w:e,h:t});Bo=!0,B.move(o.w,o.h)}else if(o===Mt){if(ne&&!Ao.getFirstOwnedPiece(e,t)){const e={x:n[1],y:n[2]},t=B.worldToViewport(e),o=Math.round(t.x-ne.x),l=Math.round(t.y-ne.y);Bo=!0,B.move(o,l),ne=t}}else if(o===Ut)K(n[1]);else if(o===Et){const e={x:n[1],y:n[2]};ne=B.worldToViewport(e),Z(!0)}else if(o===_t)ne=null,Z(!1);else if(o===Ot){const e={x:n[1],y:n[2]};Bo=!0,B.zoom("in",B.worldToViewport(e))}else if(o===Nt){const e={x:n[1],y:n[2]};Bo=!0,B.zoom("out",B.worldToViewport(e))}else o===Vt?a.togglePreview():o===$t&&a.toggleSoundsEnabled();const l=x();Ao.handleInput(e,t,n,l,(e=>{j()&&s.play()})).length>0&&(Bo=!0),tn.sendClientEvent(n)}else if("replay"===o){const e=n[0];if(e===Dt){const e=n[1],t=n[2];Bo=!0,B.move(e,t)}else if(e===Mt){if(ne){const e={x:n[1],y:n[2]},t=B.worldToViewport(e),o=Math.round(t.x-ne.x),l=Math.round(t.y-ne.y);Bo=!0,B.move(o,l),ne=t}}else if(e===Et){const e={x:n[1],y:n[2]};ne=B.worldToViewport(e)}else if(e===_t)ne=null;else if(e===Ot){const e={x:n[1],y:n[2]};Bo=!0,B.zoom("in",B.worldToViewport(e))}else if(e===Nt){const e={x:n[1],y:n[2]};Bo=!0,B.zoom("out",B.worldToViewport(e))}else e===Vt&&a.togglePreview()}F=!!Ao.getFinishTs(e),L()&&(M.update(),Bo=!0)},render:async()=>{if(!Bo)return;const n=x();let l,i,s;window.DEBUG&&_n(0),N.fillStyle=W(),N.fillRect(0,0,v.width,v.height),window.DEBUG&&Mn("clear done"),l=B.worldToViewportRaw(I),i=B.worldDimToViewportRaw(D),N.fillStyle="rgba(255, 255, 255, .3)",N.fillRect(l.x,l.y,i.w,i.h),window.DEBUG&&Mn("board done");const r=Ao.getPiecesSortedByZIndex(e);window.DEBUG&&Mn("get tiles done"),i=B.worldDimToViewportRaw(E);for(const e of r)(-1===e.owner?Oo:No)&&(s=_[e.idx],l=B.worldToViewportRaw({x:k+e.pos.x,y:k+e.pos.y}),N.drawImage(s,0,0,s.width,s.height,l.x,l.y,i.w,i.h));window.DEBUG&&Mn("tiles done");const d=[];for(const a of Ao.getActivePlayers(e,n))c=a,("replay"===o||c.id!==t)&&(s=await f(a),l=B.worldToViewport(a),N.drawImage(s,l.x-g,l.y-m),d.push([`${a.name} (${a.points})`,l.x,l.y+h]));var c;N.fillStyle="white",N.textAlign="center";for(const[e,t,o]of d)N.fillText(e,t,o);window.DEBUG&&Mn("players done"),a.setActivePlayers(Ao.getActivePlayers(e,n)),a.setIdlePlayers(Ao.getIdlePlayers(e,n)),a.setPiecesDone(Ao.getFinishedPiecesCount(e)),window.DEBUG&&Mn("HUD done"),L()&&M.render(),Bo=!1}}),{setHotkeys:e=>{U.setHotkeys(e)},onBgChange:e=>{localStorage.setItem("bg_color",e),U.addEvent([Bt,e])},onColorChange:e=>{localStorage.setItem("player_color",e),U.addEvent([Ut,e])},onNameChange:e=>{localStorage.setItem("player_name",e),U.addEvent([Rt,e])},onSoundsEnabledChange:e=>{localStorage.setItem("sound_enabled",e?"1":"0")},replayOnSpeedUp:()=>{w.speedIdx+1{w.speedIdx>=1&&(w.speedIdx--,X())},replayOnPauseToggle:()=>{w.paused=!w.paused,X()},previewImageUrl:R,player:{background:W(),color:q(),name:Ao.getPlayerName(e,t)||localStorage.getItem("player_name")||"anon",soundsEnabled:j()},disconnect:tn.disconnect,connect:C,unload:()=>{ee(),te&&te.stop()}}}var Ro=e({name:"game",components:{PuzzleStatus:ht,Scores:dt,SettingsOverlay:yt,PreviewOverlay:xt,ConnectionOverlay:nn,HelpOverlay:dn},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 Uo(`${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 Vo={id:"game"},$o={class:"menu"},Go={class:"tabs"},Fo=s("🧩 Puzzles");Ro.render=function(e,l,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",Vo,[p(n(u,{onBgclick:l[1]||(l[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":l[2]||(l[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[C,"settings"===e.overlay]]),p(n(g,{onBgclick:l[3]||(l[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[C,"preview"===e.overlay]]),p(n(h,{onBgclick:l[4]||(l[4]=t=>e.toggle("help",!0))},null,512),[[C,"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",$o,[n("div",Go,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[Fo])),_:1}),n("div",{class:"opener",onClick:l[5]||(l[5]=t=>e.toggle("preview",!1))},"πŸ–ΌοΈ Preview"),n("div",{class:"opener",onClick:l[6]||(l[6]=t=>e.toggle("settings",!0))},"πŸ› οΈ Settings"),n("div",{class:"opener",onClick:l[7]||(l[7]=t=>e.toggle("help",!0))},"ℹ️ Help")])]),n(v,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])};var Lo=e({name:"replay",components:{PuzzleStatus:ht,Scores:dt,SettingsOverlay:yt,PreviewOverlay:xt,HelpOverlay:dn},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=>{},replayOnSpeedUp:()=>{},replayOnSpeedDown:()=>{},replayOnPauseToggle:()=>{},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 Uo(`${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 jo={id:"replay"},Wo={class:"menu"},qo={class:"tabs"},Ho=s("🧩 Puzzles");Lo.render=function(e,l,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",jo,[p(n(g,{onBgclick:l[1]||(l[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":l[2]||(l[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[C,"settings"===e.overlay]]),p(n(h,{onBgclick:l[3]||(l[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[C,"preview"===e.overlay]]),p(n(m,{onBgclick:l[4]||(l[4]=t=>e.toggle("help",!0))},null,512),[[C,"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:l[5]||(l[5]=t=>e.g.replayOnSpeedUp())},"⏫"),n("button",{class:"btn",onClick:l[6]||(l[6]=t=>e.g.replayOnSpeedDown())},"⏬"),n("button",{class:"btn",onClick:l[7]||(l[7]=t=>e.g.replayOnPauseToggle())},"⏸️")])])),_:1},8,["finished","duration","piecesDone","piecesTotal"]),n("div",Wo,[n("div",qo,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[Ho])),_:1}),n("div",{class:"opener",onClick:l[8]||(l[8]=t=>e.toggle("preview",!1))},"πŸ–ΌοΈ Preview"),n("div",{class:"opener",onClick:l[9]||(l[9]=t=>e.toggle("settings",!0))},"πŸ› οΈ Settings"),n("div",{class:"opener",onClick:l[10]||(l[10]=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=k({history:A(),routes:[{name:"index",path:"/",component:L},{name:"new-game",path:"/new-game",component:Je},{name:"game",path:"/g/:id",component:Ro},{name:"replay",path:"/replay/:id",component:Lo}]});n.beforeEach(((e,t)=>{t.name&&document.documentElement.classList.remove(`view-${String(t.name)}`),document.documentElement.classList.add(`view-${String(e.name)}`)}));const o=S(z);o.config.globalProperties.$config=t,o.config.globalProperties.$clientId=function(){let e=localStorage.getItem("ID");return e||(e=ae.uniqId(),localStorage.setItem("ID",e)),e}(),o.use(n),o.mount("#app")})(); diff --git a/build/public/assets/index.ea488403.js b/build/public/assets/index.ea488403.js deleted file mode 100644 index 1cfd75f..0000000 --- a/build/public/assets/index.ea488403.js +++ /dev/null @@ -1 +0,0 @@ -import{d as e,c as t,a as n,w as o,b as l,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 w,m as v,n as b,q as x,s as C,u as k,x as A,y as S}from"./vendor.684f7bc8.js";var z=e({name:"app",computed:{showNav(){return!["game","replay"].includes(String(this.$route.name))}}});const T={id:"app"},P={key:0,class:"nav"},I=s("Index"),_=s("New game");z.render=function(e,s,r,d,c,u){const p=a("router-link"),g=a("router-view");return i(),t("div",T,[e.showNav?(i(),t("ul",P,[n("li",null,[n(p,{class:"btn",to:{name:"index"}},{default:o((()=>[I])),_:1})]),n("li",null,[n(p,{class:"btn",to:{name:"new-game"}},{default:o((()=>[_])),_:1})])])):l("",!0),n(g)])};const E=864e5,M=e=>{const t=Math.floor(e/E);e%=E;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 D=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)=>M(t-e),N=M,U=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,l=t||O();return`${n} ${B(o,l)}`}}});const R={class:"game-info-text"},V=n("br",null,null,-1),$=n("br",null,null,-1),G=n("br",null,null,-1),L=s(" β†ͺ️ Watch replay ");U.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:o((()=>[n("span",R,[s(" 🧩 "+r(e.game.tilesFinished)+"/"+r(e.game.tilesTotal),1),V,s(" πŸ‘₯ "+r(e.game.players),1),$,s(" "+r(e.time(e.game.started,e.game.finished)),1),G])])),_:1},8,["to"]),e.game.hasReplay?(i(),t(h,{key:0,class:"game-replay",to:{name:"replay",params:{id:e.game.id}}},{default:o((()=>[L])),_:1},8,["to"])):l("",!0)],4)};var F=e({components:{GameTeaser:U},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 j=n("h1",null,"Running games",-1),W=n("h1",null,"Finished games",-1);F.render=function(e,o,l,s,r,u){const p=a("game-teaser");return i(),t("div",null,[j,(i(!0),t(d,null,c(e.gamesRunning,((e,o)=>(i(),t("div",{class:"game-teaser-wrap",key:o},[n(p,{game:e},null,8,["game"])])))),128)),W,(i(!0),t(d,null,c(e.gamesFinished,((e,o)=>(i(),t("div",{class:"game-teaser-wrap",key:o},[n(p,{game:e},null,8,["game"])])))),128))])};var q=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")}}});q.render=function(e,o,l,a,s,r){return i(),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 H=e({name:"image-library",components:{ImageTeaser:q},props:{images:{type:Array,required:!0}},emits:{imageClicked:null,imageEditClicked:null},methods:{imageClicked(e){this.$emit("imageClicked",e)},imageEditClicked(e){this.$emit("imageEditClicked",e)}}});H.render=function(e,n,o,l,s,r){const u=a("image-teaser");return i(),t("div",null,[(i(!0),t(d,null,c(e.images,((n,o)=>(i(),t(u,{image:n,onClick:t=>e.imageClicked(n),onEditClick:t=>e.imageEditClicked(n),key:o},null,8,["image","onClick","onEditClick"])))),128))])};const Y={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}}}};Y.render=function(e,n,o,l,a,s){return i(),t("div",{style:s.style,title:o.title},null,12,["title"])};var Q=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.idx0?(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 Z=m();y("data-v-39ed99c7");const K={key:0,class:"autocomplete"};f();const X=Z(((e,o,a,s,u,m)=>(i(),t("div",null,[p(n("input",{ref:"input",class:"input",type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.input=t),placeholder:"Plants, People",onChange:o[2]||(o[2]=(...t)=>e.onChange&&e.onChange(...t)),onKeydown:o[3]||(o[3]=h(((...t)=>e.add&&e.add(...t)),["enter"])),onKeyup:o[4]||(o[4]=(...t)=>e.onKeyUp&&e.onKeyUp(...t))},null,544),[[g,e.input]]),e.autocomplete.values?(i(),t("div",K,[n("ul",null,[(i(!0),t(d,null,c(e.autocomplete.values,((n,o)=>(i(),t("li",{key:o,class:{active:o===e.autocomplete.idx},onClick:t=>e.addVal(n)},r(n),11,["onClick"])))),128))])])):l("",!0),(i(!0),t(d,null,c(e.values,((n,o)=>(i(),t("span",{key:o,class:"bit",onClick:t=>e.rm(n)},r(n)+" βœ–",9,["onClick"])))),128))]))));Q.render=X,Q.__scopeId="data-v-39ed99c7";var J=e({name:"new-image-dialog",components:{ResponsiveImage:Y,TagsInput:Q},props:{autocompleteTags:{type:Function}},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 ee={key:0,class:"has-image"},te={key:1},ne={class:"upload"},oe=n("span",{class:"btn"},"Upload File",-1),le={class:"area-settings"},ae=n("td",null,[n("label",null,"Title")],-1),ie=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),se=n("td",null,[n("label",null,"Tags")],-1),re={class:"area-buttons"},de=s("🧩 Post to gallery "),ce=n("br",null,null,-1),ue=s(" + set up game");J.render=function(e,o,l,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),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?(i(),t("div",ee,[n("span",{class:"remove btn",onClick:o[1]||(o[1]=t=>e.previewUrl="")},"X"),n(c,{src:e.previewUrl},null,8,["src"])])):(i(),t("div",te,[n("label",ne,[n("input",{type:"file",style:{display:"none"},onChange:o[2]||(o[2]=(...t)=>e.preview&&e.preview(...t)),accept:"image/*"},null,32),oe])]))],2),n("div",le,[n("table",null,[n("tr",null,[ae,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[3]||(o[3]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),ie,n("tr",null,[se,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[4]||(o[4]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",re,[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))},[de,ce,ue],8,["disabled"])])])])};var pe=e({name:"edit-image-dialog",components:{ResponsiveImage:Y,TagsInput:Q},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 ge={class:"area-image"},he={class:"has-image"},me={class:"area-settings"},ye=n("td",null,[n("label",null,"Title")],-1),fe=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),we=n("td",null,[n("label",null,"Tags")],-1),ve={class:"area-buttons"};var be,xe,Ce,ke,Ae,Se,ze,Te;pe.render=function(e,o,l,s,r,d){const c=a("responsive-image"),h=a("tags-input");return i(),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",ge,[n("div",he,[n(c,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",me,[n("table",null,[n("tr",null,[ye,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.title=t),placeholder:"Flower by @artist"},null,512),[[g,e.title]])])]),fe,n("tr",null,[we,n("td",null,[n(h,{modelValue:e.tags,"onUpdate:modelValue":o[2]||(o[2]=t=>e.tags=t),autocompleteTags:e.autocompleteTags},null,8,["modelValue","autocompleteTags"])])])])]),n("div",ve,[n("button",{class:"btn",onClick:o[3]||(o[3]=(...t)=>e.saveImage&&e.saveImage(...t))},"πŸ–ΌοΈ Save image")])])])},(xe=be||(be={}))[xe.Flat=0]="Flat",xe[xe.Out=1]="Out",xe[xe.In=-1]="In",(ke=Ce||(Ce={}))[ke.FINAL=0]="FINAL",ke[ke.ANY=1]="ANY",(Se=Ae||(Ae={}))[Se.NORMAL=0]="NORMAL",Se[Se.ANY=1]="ANY",Se[Se.FLAT=2]="FLAT",(Te=ze||(ze={}))[Te.NORMAL=0]="NORMAL",Te[Te.REAL=1]="REAL";var Pe=e({name:"new-game-dialog",components:{ResponsiveImage:Y},props:{image:{type:Object,required:!0}},emits:{newGame:null,bgclick:null},data:()=>({tiles:1e3,scoreMode:Ce.ANY,shapeMode:Ae.NORMAL,snapMode:ze.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 Ie={class:"area-image"},_e={class:"has-image"},Ee={class:"area-settings"},Me=n("td",null,[n("label",null,"Pieces")],-1),De=n("td",null,[n("label",null,"Scoring: ")],-1),Oe=s(" Any (Score when pieces are connected to each other or on final location)"),Be=n("br",null,null,-1),Ne=s(" Final (Score when pieces are put to their final location)"),Ue=n("td",null,[n("label",null,"Shapes: ")],-1),Re=s(" Normal"),Ve=n("br",null,null,-1),$e=s(" Any (flat pieces can occur anywhere)"),Ge=n("br",null,null,-1),Le=s(" Flat (all pieces flat on all sides)"),Fe=n("td",null,[n("label",null,"Snapping: ")],-1),je=s(" Normal (pieces snap to final destination and to each other)"),We=n("br",null,null,-1),qe=s(" Real (pieces snap only to corners, already snapped pieces and to each other)"),He={class:"area-buttons"};Pe.render=function(e,o,l,s,r,d){const c=a("responsive-image");return i(),t("div",{class:"overlay new-game-dialog",onClick:o[11]||(o[11]=t=>e.$emit("bgclick"))},[n("div",{class:"overlay-content",onClick:o[10]||(o[10]=u((()=>{}),["stop"]))},[n("div",Ie,[n("div",_e,[n(c,{src:e.image.url,title:e.image.title},null,8,["src","title"])])]),n("div",Ee,[n("table",null,[n("tr",null,[Me,n("td",null,[p(n("input",{type:"text","onUpdate:modelValue":o[1]||(o[1]=t=>e.tiles=t)},null,512),[[g,e.tiles]])])]),n("tr",null,[De,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[2]||(o[2]=t=>e.scoreMode=t),value:"1"},null,512),[[w,e.scoreMode]]),Oe]),Be,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[3]||(o[3]=t=>e.scoreMode=t),value:"0"},null,512),[[w,e.scoreMode]]),Ne])])]),n("tr",null,[Ue,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[4]||(o[4]=t=>e.shapeMode=t),value:"0"},null,512),[[w,e.shapeMode]]),Re]),Ve,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[5]||(o[5]=t=>e.shapeMode=t),value:"1"},null,512),[[w,e.shapeMode]]),$e]),Ge,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[6]||(o[6]=t=>e.shapeMode=t),value:"2"},null,512),[[w,e.shapeMode]]),Le])])]),n("tr",null,[Fe,n("td",null,[n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[7]||(o[7]=t=>e.snapMode=t),value:"0"},null,512),[[w,e.snapMode]]),je]),We,n("label",null,[p(n("input",{type:"radio","onUpdate:modelValue":o[8]||(o[8]=t=>e.snapMode=t),value:"1"},null,512),[[w,e.snapMode]]),qe])])])])]),n("div",He,[n("button",{class:"btn",disabled:!e.canStartNewGame,onClick:o[9]||(o[9]=(...t)=>e.onNewGameClick&&e.onNewGameClick(...t))}," 🧩 Generate Puzzle ",8,["disabled"])])])])};class Ye{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 Ye(0);return t.rand_high=e.rand_high,t.rand_low=e.rand_low,t}}const Qe=(e,t)=>{const n=`${e}`;return n.length>=t.length?n:t.substr(0,t.length-n.length)+n},Ze=(...e)=>{const t=t=>(...n)=>{const o=new Date,l=Qe(o.getHours(),"00"),a=Qe(o.getMinutes(),"00"),i=Qe(o.getSeconds(),"00");console[t](`${l}:${a}:${i}`,...e,...n)};return{log:t("log"),error:t("error"),info:t("info")}};var Ke={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||"",Ye.serialize(e.rng.obj),e.puzzle,e.players,e.evtInfos,e.scoreMode||Ce.FINAL,e.shapeMode||Ae.ANY,e.snapMode||ze.NORMAL]},decodeGame:function(e){return{id:e[0],rng:{type:e[1],obj:Ye.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 o=[n,e[n]].map(encodeURIComponent);t.push(o.join("="))}return 0===t.length?"":`?${t.join("&")}`}},Xe=e({components:{ImageLibrary:H,NewImageDialog:J,EditImageDialog:pe,NewGameDialog:Pe},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${Ke.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 Je={class:"upload-image-teaser"},et=n("div",{class:"hint"},"(The image you upload will be added to the public gallery.)",-1),tt={key:0},nt=s(" Tags: "),ot=s(" Sort by: "),lt=n("option",{value:"date_desc"},"Newest first",-1),at=n("option",{value:"date_asc"},"Oldest first",-1),it=n("option",{value:"alpha_asc"},"A-Z",-1),st=n("option",{value:"alpha_desc"},"Z-A",-1);Xe.render=function(e,o,s,u,g,h){const m=a("image-library"),y=a("new-image-dialog"),f=a("edit-image-dialog"),w=a("new-game-dialog");return i(),t("div",null,[n("div",Je,[n("div",{class:"btn btn-big",onClick:o[1]||(o[1]=t=>e.dialog="new-image")},"Upload your image"),et]),n("div",null,[e.tags.length>0?(i(),t("label",tt,[nt,(i(!0),t(d,null,c(e.relevantTags,((n,o)=>(i(),t("span",{class:["bit",{on:e.filters.tags.includes(n.slug)}],key:o,onClick:t=>e.toggleTag(n)},r(n.title)+" ("+r(n.total)+")",11,["onClick"])))),128))])):l("",!0),n("label",null,[ot,p(n("select",{"onUpdate:modelValue":o[2]||(o[2]=t=>e.filters.sort=t),onChange:o[3]||(o[3]=(...t)=>e.filtersChanged&&e.filtersChanged(...t))},[lt,at,it,st],544),[[v,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:o[4]||(o[4]=t=>e.dialog=""),onPostToGalleryClick:e.postToGalleryClick,onSetupGameClick:e.setupGameClick},null,8,["autocompleteTags","onPostToGalleryClick","onSetupGameClick"])):l("",!0),"edit-image"===e.dialog?(i(),t(f,{key:1,autocompleteTags:e.autocompleteTags,onBgclick:o[5]||(o[5]=t=>e.dialog=""),onSaveClick:e.onSaveImageClick,image:e.image},null,8,["autocompleteTags","onSaveClick","image"])):l("",!0),e.image&&"new-game"===e.dialog?(i(),t(w,{key:2,onBgclick:o[6]||(o[6]=t=>e.dialog=""),onNewGame:e.onNewGame,image:e.image},null,8,["onNewGame","image"])):l("",!0)])};var rt=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 dt={class:"scores"},ct=n("div",null,"Scores",-1),ut=n("td",null,"⚑",-1),pt=n("td",null,"πŸ’€",-1);rt.render=function(e,o,l,a,s,u){return i(),t("div",dt,[ct,n("table",null,[(i(!0),t(d,null,c(e.actives,((e,o)=>(i(),t("tr",{key:o,style:{color:e.color}},[ut,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,o)=>(i(),t("tr",{key:o,style:{color:e.color}},[pt,n("td",null,r(e.name),1),n("td",null,r(e.points),1)],4)))),128))])])};var gt=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 N(this.duration)}}});const ht={class:"timer"};gt.render=function(e,o,l,a,s,d){return i(),t("div",ht,[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 mt=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 yt=n("td",null,[n("label",null,"Background: ")],-1),ft=n("td",null,[n("label",null,"Color: ")],-1),wt=n("td",null,[n("label",null,"Name: ")],-1),vt=n("td",null,[n("label",null,"Sounds: ")],-1);mt.render=function(e,o,l,a,s,r){return i(),t("div",{class:"overlay transparent",onClick:o[6]||(o[6]=t=>e.$emit("bgclick"))},[n("table",{class:"overlay-content settings",onClick:o[5]||(o[5]=u((()=>{}),["stop"]))},[n("tr",null,[yt,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":o[1]||(o[1]=t=>e.modelValue.background=t)},null,512),[[g,e.modelValue.background]])])]),n("tr",null,[ft,n("td",null,[p(n("input",{type:"color","onUpdate:modelValue":o[2]||(o[2]=t=>e.modelValue.color=t)},null,512),[[g,e.modelValue.color]])])]),n("tr",null,[wt,n("td",null,[p(n("input",{type:"text",maxLength:"16","onUpdate:modelValue":o[3]||(o[3]=t=>e.modelValue.name=t)},null,512),[[g,e.modelValue.name]])])]),n("tr",null,[vt,n("td",null,[p(n("input",{type:"checkbox","onUpdate:modelValue":o[4]||(o[4]=t=>e.modelValue.soundsEnabled=t)},null,512),[[x,e.modelValue.soundsEnabled]])])])])])};var bt=e({name:"preview-overlay",props:{img:String},emits:{bgclick:null},computed:{previewStyle(){return{backgroundImage:`url('${this.img}')`}}}});const xt={class:"preview"};bt.render=function(e,o,l,a,s,r){return i(),t("div",{class:"overlay",onClick:o[1]||(o[1]=t=>e.$emit("bgclick"))},[n("div",xt,[n("div",{class:"img",style:e.previewStyle},null,4)])])};var Ct=1,kt=4,At=2,St=3,zt=2,Tt=4,Pt=3,It=9,_t=1,Et=2,Mt=3,Dt=4,Ot=5,Bt=6,Nt=7,Ut=8,Rt=10,Vt=11,$t=1,Gt=2,Lt=3;const Ft=Ze("Communication.js");let jt,Wt=[],qt=e=>{Wt.push(e)},Ht=[],Yt=e=>{Ht.push(e)};let Qt=0;const Zt=e=>{Qt!==e&&(Qt=e,Yt(e))};function Kt(e){if(2===Qt)try{jt.send(JSON.stringify(e))}catch(t){Ft.info("unable to send message.. maybe because ws is invalid?")}}let Xt,Jt;var en={connect:function(e,t,n){return Xt=0,Jt={},Zt(3),new Promise((o=>{jt=new WebSocket(e,n+"|"+t),jt.onopen=()=>{Zt(2),Kt([St])},jt.onmessage=e=>{const t=JSON.parse(e.data),l=t[0];if(l===kt){const e=t[1];o(e)}else{if(l!==Ct)throw`[ 2021-05-09 invalid connect msgType ${l} ]`;{const e=t[1],o=t[2];if(e===n&&Jt[o])return void delete Jt[o];qt(t)}}},jt.onerror=()=>{throw Zt(1),"[ 2021-05-15 onerror ]"},jt.onclose=e=>{4e3===e.code||1001===e.code?Zt(4):Zt(1)}}))},requestReplayData:async function(e,t,n){const o={gameId:e,offset:t,size:n},l=await fetch(`/api/replay-data${Ke.asQueryArgs(o)}`);return await l.json()},disconnect:function(){jt&&jt.close(4e3),Xt=0,Jt={}},sendClientEvent:function(e){Xt++,Jt[Xt]=e,Kt([At,Xt,Jt[Xt]])},onServerChange:function(e){qt=e;for(const t of Wt)qt(t);Wt=[]},onConnectionStateChange:function(e){Yt=e;for(const t of Ht)Yt(t);Ht=[]},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},tn=e({name:"connection-overlay",emits:{reconnect:null},props:{connectionState:Number},computed:{lostConnection(){return this.connectionState===en.CONN_STATE_DISCONNECTED},connecting(){return this.connectionState===en.CONN_STATE_CONNECTING},show(){return!(!this.lostConnection&&!this.connecting)}}});const nn={key:0,class:"overlay connection-lost"},on={key:0,class:"overlay-content"},ln=n("div",null,"⁉️ LOST CONNECTION ⁉️",-1),an={key:1,class:"overlay-content"},sn=n("div",null,"Connecting...",-1);tn.render=function(e,o,a,s,r,d){return e.show?(i(),t("div",nn,[e.lostConnection?(i(),t("div",on,[ln,n("span",{class:"btn",onClick:o[1]||(o[1]=t=>e.$emit("reconnect"))},"Reconnect")])):l("",!0),e.connecting?(i(),t("div",an,[sn])):l("",!0)])):l("",!0)};var rn=e({name:"help-overlay",emits:{bgclick:null}});const dn=n("tr",null,[n("td",null,"⬆️ Move up:"),n("td",null,[n("div",null,[n("kbd",null,"W"),s("/"),n("kbd",null,"↑"),s("/πŸ–±οΈ")])])],-1),cn=n("tr",null,[n("td",null,"⬇️ Move down:"),n("td",null,[n("div",null,[n("kbd",null,"S"),s("/"),n("kbd",null,"↓"),s("/πŸ–±οΈ")])])],-1),un=n("tr",null,[n("td",null,"⬅️ Move left:"),n("td",null,[n("div",null,[n("kbd",null,"A"),s("/"),n("kbd",null,"←"),s("/πŸ–±οΈ")])])],-1),pn=n("tr",null,[n("td",null,"➑️ Move right:"),n("td",null,[n("div",null,[n("kbd",null,"D"),s("/"),n("kbd",null,"β†’"),s("/πŸ–±οΈ")])])],-1),gn=n("tr",null,[n("td"),n("td",null,[n("div",null,[s("Move faster by holding "),n("kbd",null,"Shift")])])],-1),hn=n("tr",null,[n("td",null,"πŸ”+ Zoom in:"),n("td",null,[n("div",null,[n("kbd",null,"E"),s("/πŸ–±οΈ-Wheel")])])],-1),mn=n("tr",null,[n("td",null,"πŸ”- Zoom out:"),n("td",null,[n("div",null,[n("kbd",null,"Q"),s("/πŸ–±οΈ-Wheel")])])],-1),yn=n("tr",null,[n("td",null,"πŸ–ΌοΈ Toggle preview:"),n("td",null,[n("div",null,[n("kbd",null,"Space")])])],-1),fn=n("tr",null,[n("td",null,"πŸ§©βœ”οΈ Toggle fixed pieces:"),n("td",null,[n("div",null,[n("kbd",null,"F")])])],-1),wn=n("tr",null,[n("td",null,"πŸ§©β“ Toggle loose pieces:"),n("td",null,[n("div",null,[n("kbd",null,"G")])])],-1),vn=n("tr",null,[n("td",null,"πŸ”‰ Toggle sounds:"),n("td",null,[n("div",null,[n("kbd",null,"M")])])],-1);rn.render=function(e,o,l,a,s,r){return i(),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"]))},[dn,cn,un,pn,gn,hn,mn,yn,fn,wn,vn])])};var bn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"/assets/click.bb97cb07.mp3"}),xn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAW0lEQVQ4je1RywrAIAxLxP//5exixRWlVgZelpOKeTQFfnDypgy3eLIkSLLL8mxGPoHsU2hPAgDHBLvRX6hZZw/fwT0BtlLSONqCbWAmEIqMZOCDDlaDR3N03gOyDCn+y4DWmAAAAABJRU5ErkJggg=="}),Cn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAARElEQVQ4jWNgGAU0Af+hmBCbgYGBgYERhwHEAEYGBgYGJtIdiApYyLAZBVDsAqoagC1ACQJyY4ERg0GCISh6KA4DigEAou8LC+LnIJoAAAAASUVORK5CYII="}),kn=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAcUlEQVQ4ja1TQQ7AIAgD///n7jCozA2Hbk00jbG1KIrcARszTugoBs49qioZj7r2kKACptkyAOCJsJuA+GzglwHjvMSSWFVaENWVASxh5eRLiq5fN/ASjI89VcP2K3hHpq1cEXNaMfnrL3TDZP2tDuoOA6MzCCXWr38AAAAASUVORK5CYII="}),An=Object.freeze({__proto__:null,[Symbol.toStringTag]:"Module",default:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAU0lEQVQ4jWNgoAH4D8X42HDARKlt5BoAd82AuQAOGLGIYQQUPv0wF5CiCQUge4EsQ5C9QI4BjMguwBYeBAElscCIy1ZivMKIwSDBEBQ9FCckigEAU3QOD7TGvY4AAAAASUVORK5CYII="});function Sn(){let e=0,t=0,n=1;const o=(o,l)=>{e+=o/n,t+=l/n},l=e=>{const t=n+.05*n*("in"===e?1:-1);return Math.min(Math.max(t,.1),6)},a=o=>({x:o.x/n-e,y:o.y/n-t}),i=o=>({x:(o.x+e)*n,y:(o.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:o,canZoom:e=>n!=l(e),zoom:(e,t)=>((e,t)=>{if(n==e)return!1;const l=1-n/e;return o(-t.x*l,-t.y*l),n=e,!0})(l(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 zn(e=0,t=0){const n=document.createElement("canvas");return n.width=e,n.height=t,n}var Tn={createCanvas:zn,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=zn(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=zn(e.width,e.height),l=o.getContext("2d");return l.save(),l.drawImage(t,0,0),l.fillStyle=n,l.globalCompositeOperation="source-in",l.fillRect(0,0,t.width,t.height),l.restore(),l.save(),l.globalCompositeOperation="destination-over",l.drawImage(e,0,0),l.restore(),o}};const Pn=Ze("Debug.js");let In=0,_n=0;var En=e=>{In=performance.now(),_n=e},Mn=e=>{const t=performance.now(),n=t-In;n>_n&&Pn.log(e+": "+n),In=t};function Dn(e,t){const n=e.x-t.x,o=e.y-t.y;return Math.sqrt(n*n+o*o)}function On(e){return{x:e.x+e.w/2,y:e.y+e.h/2}}var Bn={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:Dn,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:On,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 Dn(On(e),On(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 Nn=Ze("PuzzleGraphics.js");function Un(e,t){const n=Ke.coordByPieceIdx(e,t);return{x:n.x*e.tileSize,y:n.y*e.tileSize,w:e.tileSize,h:e.tileSize}}var Rn={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){Nn.log("start createPuzzleTileBitmaps");const o=n.tileSize,l=n.tileMarginWidth,a=n.tileDrawSize,i=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),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:l,y:l},r=Bn.pointAdd(a,{x:o,y:0}),c=Bn.pointAdd(r,{x:0,y:o}),u=Bn.pointSub(c,{x:o,y:0});if(n.moveTo(a.x,a.y),0!==e.top)for(let o=0;oKe.decodePiece(Vn[e].puzzle.tiles[t]),Jn=(e,t)=>Xn(e,t).group,eo=(e,t)=>{const n=Vn[e].puzzle.info;return 0===t||t===n.tilesX-1||t===n.tiles-n.tilesX||t===n.tiles-1},to=(e,t)=>{const n=Vn[e].puzzle.info,o={x:(n.table.width-n.width)/2,y:(n.table.height-n.height)/2},l=function(e,t){const n=Vn[e].puzzle.info,o=Ke.coordByPieceIdx(n,t),l=o.x*n.tileSize,a=o.y*n.tileSize;return{x:l,y:a}}(e,t);return Bn.pointAdd(o,l)},no=(e,t)=>Xn(e,t).pos,oo=e=>{const t=xo(e),n=Co(e),o=Math.round(t/4),l=Math.round(n/4);return{x:0-o,y:0-l,w:t+2*o,h:n+2*l}},lo=(e,t)=>{const n=ro(e),o=Xn(e,t);return{x:o.pos.x,y:o.pos.y,w:n,h:n}},ao=(e,t)=>Xn(e,t).z,io=(e,t)=>{for(const n of Vn[e].puzzle.tiles){const e=Ke.decodePiece(n);if(e.owner===t)return e.idx}return-1},so=e=>Vn[e].puzzle.info.tileDrawSize,ro=e=>Vn[e].puzzle.info.tileSize,co=e=>Vn[e].puzzle.data.maxGroup,uo=e=>Vn[e].puzzle.data.maxZ;function po(e,t){const n=Vn[e].puzzle.info,o=Ke.coordByPieceIdx(n,t);return[o.y>0?t-n.tilesX:-1,o.x0?t-1:-1]}const go=(e,t,n)=>{for(const o of t)Kn(e,o,{z:n})},ho=(e,t,n)=>{const o=no(e,t);Kn(e,t,{pos:Bn.pointAdd(o,n)})},mo=(e,t,n)=>{const o=so(e),l=oo(e),a=n;for(const i of t){const t=Xn(e,i);t.pos.x+n.xl.x+l.w&&(a.x=Math.min(l.x+l.w-t.pos.x+o,a.x)),t.pos.y+n.yl.y+l.h&&(a.y=Math.min(l.y+l.h-t.pos.y+o,a.y))}for(const i of t)ho(e,i,a)},yo=(e,t)=>Xn(e,t).owner,fo=(e,t)=>{for(const n of t)Kn(e,n,{owner:-1,z:1})},wo=(e,t,n)=>{for(const o of t)Kn(e,o,{owner:n})};function vo(e,t){const n=Vn[e].puzzle.tiles,o=Ke.decodePiece(n[t]),l=[];if(o.group)for(const a of n){const e=Ke.decodePiece(a);e.group===o.group&&l.push(e.idx)}else l.push(o.idx);return l}const bo=(e,t)=>{const n=Gn(e,t);return n?n.points:0},xo=e=>Vn[e].puzzle.info.table.width,Co=e=>Vn[e].puzzle.info.table.height;var ko={setGame:function(e,t){Vn[e]=t},exists:function(e){return!!Vn[e]||!1},playerExists:Fn,getActivePlayers:function(e,t){const n=t-30*D;return jn(e).filter((e=>e.ts>=n))},getIdlePlayers:function(e,t){const n=t-30*D;return jn(e).filter((e=>e.ts0))},addPlayer:function(e,t,n){Fn(e,t)?Qn(e,t,{ts:n}):Ln(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:Yn,getPieceCount:Wn,getImageUrl:function(e){return Vn[e].puzzle.info.imageUrl},setImageUrl:function(e,t){Vn[e].puzzle.info.imageUrl=t},get:function(e){return Vn[e]||null},getAllGames:function(){return Object.values(Vn).sort(((e,t)=>Hn(e.id)===Hn(t.id)?t.puzzle.data.started-e.puzzle.data.started:Hn(e.id)?1:-1))},getPlayerBgColor:(e,t)=>{const n=Gn(e,t);return n?n.bgcolor:null},getPlayerColor:(e,t)=>{const n=Gn(e,t);return n?n.color:null},getPlayerName:(e,t)=>{const n=Gn(e,t);return n?n.name:null},getPlayerIndexById:$n,getPlayerIdByIndex:function(e,t){return Vn[e].players.length>t?Ke.decodePlayer(Vn[e].players[t]).id:null},changePlayer:Qn,setPlayer:Ln,setPiece:function(e,t,n){Vn[e].puzzle.tiles[t]=Ke.encodePiece(n)},setPuzzleData:function(e,t){Vn[e].puzzle.data=t},getTableWidth:xo,getTableHeight:Co,getPuzzle:e=>Vn[e].puzzle,getRng:e=>Vn[e].rng.obj,getPuzzleWidth:e=>Vn[e].puzzle.info.width,getPuzzleHeight:e=>Vn[e].puzzle.info.height,getPiecesSortedByZIndex:function(e){return Vn[e].puzzle.tiles.map(Ke.decodePiece).sort(((e,t)=>e.z-t.z))},getFirstOwnedPiece:(e,t)=>{const n=io(e,t);return n<0?null:Vn[e].puzzle.tiles[n]},getPieceDrawOffset:e=>Vn[e].puzzle.info.tileDrawOffset,getPieceDrawSize:so,getFinalPiecePos:to,getStartTs:e=>Vn[e].puzzle.data.started,getFinishTs:e=>Vn[e].puzzle.data.finished,handleInput:function(e,t,n,o,l){const a=Vn[e].puzzle,i=function(e,t){return t in Vn[e].evtInfos?Vn[e].evtInfos[t]:{_last_mouse:null,_last_mouse_down:null}}(e,t),s=[],r=()=>{s.push([$t,a.data])},d=t=>{s.push([Gt,Ke.encodePiece(Xn(e,t))])},c=e=>{for(const t of e)d(t)},u=()=>{const n=Gn(e,t);n&&s.push([Lt,Ke.encodePlayer(n)])},p=n[0];if(p===Bt){const l=n[1];Qn(e,t,{bgcolor:l,ts:o}),u()}else if(p===Nt){const l=n[1];Qn(e,t,{color:l,ts:o}),u()}else if(p===Ut){const l=`${n[1]}`.substr(0,16);Qn(e,t,{name:l,ts:o}),u()}else if(p===It){const l=n[1],a=n[2],i=Gn(e,t);if(i){const n=i.x-l,s=i.y-a;Qn(e,t,{ts:o,x:n,y:s}),u()}}else if(p===_t){const l={x:n[1],y:n[2]};Qn(e,t,{d:1,ts:o}),u(),i._last_mouse_down=l;const a=((e,t)=>{const n=Vn[e].puzzle.info,o=Vn[e].puzzle.tiles;let l=-1,a=-1;for(let i=0;il)&&(l=e.z,a=i)}return a})(e,l);if(a>=0){const n=uo(e)+1;Zn(e,{maxZ:n}),r();const o=vo(e,a);go(e,o,uo(e)),wo(e,o,t),c(o)}i._last_mouse=l}else if(p===Mt){const l=n[1],a=n[2],s={x:l,y:a};if(null===i._last_mouse_down)Qn(e,t,{x:l,y:a,ts:o}),u();else{const n=io(e,t);if(n>=0){Qn(e,t,{x:l,y:a,ts:o}),u();const r=vo(e,n);let d=Bn.pointInBounds(s,oo(e))&&Bn.pointInBounds(i._last_mouse_down,oo(e));for(const t of r){const n=lo(e,t);if(Bn.pointInBounds(s,n)){d=!0;break}}if(d){const t=l-i._last_mouse_down.x,n=a-i._last_mouse_down.y;mo(e,r,{x:t,y:n}),c(r)}}else Qn(e,t,{ts:o}),u();i._last_mouse_down=s}i._last_mouse=s}else if(p===Et){const s={x:n[1],y:n[2]},p=0;i._last_mouse_down=null;const g=io(e,t);if(g>=0){const n=vo(e,g);wo(e,n,0),c(n);const i=no(e,g),s=to(e,g);let h=!1;if(function(e){return Vn[e].snapMode||ze.NORMAL}(e)===ze.REAL){for(const t of n)if(eo(e,t)){h=!0;break}}else h=!0;if(h&&Bn.pointDistance(s,i){const l=Vn[e].puzzle.info;if(n<0)return!1;if(((e,t,n)=>{const o=Jn(e,t),l=Jn(e,n);return!(!o||o!==l)})(e,t,n))return!1;const a=no(e,t),i=Bn.pointAdd(no(e,n),{x:o[0]*l.tileSize,y:o[1]*l.tileSize});if(Bn.pointDistance(a,i){const o=Vn[e].puzzle.tiles,l=Jn(e,t),a=Jn(e,n);let i;const s=[];l&&s.push(l),a&&s.push(a),l?i=l:a?i=a:(Zn(e,{maxGroup:co(e)+1}),r(),i=co(e));if(Kn(e,t,{group:i}),d(t),Kn(e,n,{group:i}),d(n),s.length>0)for(const r of o){const t=Ke.decodePiece(r);s.includes(t.group)&&(Kn(e,t.idx,{group:i}),d(t.idx))}})(e,t,n),l=vo(e,t),((e,t)=>-1===yo(e,t))(e,n))fo(e,l);else{const t=((e,t)=>{let n=0;for(const o of t){const t=ao(e,o);t>n&&(n=t)}return n})(e,l);go(e,l,t)}return c(l),!0}return!1};let a=!1;for(const t of vo(e,g)){const o=po(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])){a=!0;break}}if(a&&qn(e)===Ce.ANY){const n=bo(e,t)+1;Qn(e,t,{d:p,ts:o,points:n}),u()}else Qn(e,t,{d:p,ts:o}),u();a&&l&&l(t)}}else Qn(e,t,{d:p,ts:o}),u();i._last_mouse=s}else if(p===Dt){const l=n[1],a=n[2];Qn(e,t,{x:l,y:a,ts:o}),u(),i._last_mouse={x:l,y:a}}else if(p===Ot){const l=n[1],a=n[2];Qn(e,t,{x:l,y:a,ts:o}),u(),i._last_mouse={x:l,y:a}}else Qn(e,t,{ts:o}),u();return function(e,t,n){Vn[e].evtInfos[t]=n}(e,t,i),s}};let Ao=-10,So=20,zo=2,To=15;class Po{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=Ao+Math.random()*So,this.vy=-1*(zo+Math.random()*To),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;zo=t/2,To=t-zo;const n=1/4*this.canvas.width/(t/2);Ao=-n,So=2*n}resize(){this.setSpeedParams()}init(){this.readyBombs=[],this.explodedBombs=[],this.particles=[];for(let e=0;e<1;e++)this.readyBombs.push(new Po(this.rng))}update(){100*Math.random()<5&&this.readyBombs.push(new Po(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(!y[t]){const n=e.d?r:d;if(e.color){const o=e.d?c:u;y[t]=await createImageBitmap(Tn.colorizedCanvas(n,o,e.color))}else y[t]=n}return y[t]},w=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,Bo=!0})),t}(l,Tn.createCanvas()),v={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};en.onConnectionStateChange((e=>{a.setConnectionState(e)}));const b=async e=>{v.requesting=!0;const t=await en.requestReplayData(e,v.dataOffset,v.dataSize);return v.dataOffset+=v.dataSize,v.requesting=!1,t};let x=()=>0;const C=async()=>{if("play"===o){const o=await en.connect(n,e,t),l=Ke.decodeGame(o);ko.setGame(l.id,l),x=()=>O()}else{if("replay"!==o)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=Ke.decodeGame(t.game);ko.setGame(n.id,n),v.requesting=!1,v.log=t.log,v.lastRealTs=O(),v.gameStartTs=parseInt(v.log[0][4],10),v.lastGameTs=v.gameStartTs,v.final=!1,v.logPointer=0,v.speeds=[.5,1,2,5,10,20,50,100,250,500],v.speedIdx=1,v.paused=!1,v.dataOffset=0,v.dataSize=1e4,x=()=>v.lastGameTs}}Bo=!0};await C();const k=ko.getPieceDrawOffset(e),A=ko.getPieceDrawSize(e),S=ko.getPuzzleWidth(e),z=ko.getPuzzleHeight(e),T=ko.getTableWidth(e),P=ko.getTableHeight(e),I={x:(T-S)/2,y:(P-z)/2},_={w:S,h:z},E={w:A,h:A},M=await Rn.loadPuzzleBitmaps(ko.getPuzzle(e)),D=new _o(w,ko.getRng(e));D.init();const B=w.getContext("2d");w.classList.add("loaded");const N=Sn();N.move(-(T-w.width)/2,-(P-w.height)/2);const U=function(e,t,n){let o=[],l=!0,a=!1,i=!1,s=!1,r=!1,d=!1,c=!1,u=!1;const p=(e,t)=>{const o=n.viewportToWorld({x:e,y:t});return[o.x,o.y]},g=e=>p(e.offsetX,e.offsetY),h=()=>p(e.width/2,e.height/2),m=(e,t)=>{l&&("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?a=e:"ArrowRight"===t.key||"d"===t.key||"D"===t.key?i=e:"q"===t.key?c=e:"e"===t.key&&(d=e))};let y=null;e.addEventListener("mousedown",(e=>{y=g(e),0===e.button&&f([_t,...y])})),e.addEventListener("mouseup",(e=>{y=g(e),0===e.button&&f([Et,...y])})),e.addEventListener("mousemove",(e=>{y=g(e),f([Mt,...y])})),e.addEventListener("wheel",(e=>{if(y=g(e),n.canZoom(e.deltaY<0?"in":"out")){const t=e.deltaY<0?Dt:Ot;f([t,...y])}})),t.addEventListener("keydown",(e=>m(!0,e))),t.addEventListener("keyup",(e=>m(!1,e))),t.addEventListener("keypress",(e=>{l&&(" "===e.key&&f([Rt]),"F"!==e.key&&"f"!==e.key||(Do=!Do,Bo=!0),"G"!==e.key&&"g"!==e.key||(Oo=!Oo,Bo=!0),"M"!==e.key&&"m"!==e.key||f([Vt]))}));const f=e=>{o.push(e)};return{addEvent:f,consumeAll:()=>{if(0===o.length)return[];const e=o.slice();return o=[],e},createKeyEvents:()=>{const e=(a?1:0)-(i?1:0),t=(s?1:0)-(r?1:0);if(0!==e||0!==t){const o=(u?24:12)*Math.sqrt(n.getCurrentZoom()),l=n.viewportDimToWorld({w:e*o,h:t*o});f([It,l.w,l.h]),y&&(y[0]-=l.w,y[1]-=l.h)}if(d&&c);else if(d){if(n.canZoom("in")){const e=y||h();f([Dt,...e])}}else if(c&&n.canZoom("out")){const e=y||h();f([Ot,...e])}},setHotkeys:e=>{l=e}}}(w,window,N),R=ko.getImageUrl(e),V=()=>{const t=ko.getStartTs(e),n=ko.getFinishTs(e),o=x();a.setFinished(!!n),a.setDuration((n||o)-t)};V(),a.setPiecesDone(ko.getFinishedPiecesCount(e)),a.setPiecesTotal(ko.getPieceCount(e));const $=x();a.setActivePlayers(ko.getActivePlayers(e,$)),a.setIdlePlayers(ko.getIdlePlayers(e,$));const G=!!ko.getFinishTs(e);let L=G;const F=()=>L&&!G,j=()=>{const e=localStorage.getItem("sound_enabled");return null!==e&&"1"===e},W=()=>ko.getPlayerBgColor(e,t)||localStorage.getItem("bg_color")||"#222222",q=()=>ko.getPlayerColor(e,t)||localStorage.getItem("player_color")||"#ffffff";let H="",Y="",Q=!1;const Z=e=>{Q=e;const[t,n]=e?[H,"grab"]:[Y,"default"];w.style.cursor=`url('${t}') ${g} ${m}, ${n}`},K=e=>{H=Tn.colorizedCanvas(r,c,e).toDataURL(),Y=Tn.colorizedCanvas(d,u,e).toDataURL(),Z(Q)};K(q());const X=()=>{a.setReplaySpeed&&a.setReplaySpeed(v.speeds[v.speedIdx]),a.setReplayPaused&&a.setReplayPaused(v.paused)},J=[],ee=()=>{J.forEach((e=>{clearInterval(e)}))};let te;"play"===o?J.push(setInterval((()=>{V()}),1e3)):"replay"===o&&X(),"play"===o?en.onServerChange((n=>{n[0],n[1],n[2];const o=n[3];for(const[l,a]of o)switch(l){case Lt:{const n=Ke.decodePlayer(a);n.id!==t&&(ko.setPlayer(e,n.id,n),Bo=!0)}break;case Gt:{const t=Ke.decodePiece(a);ko.setPiece(e,t.idx,t),Bo=!0}break;case $t:ko.setPuzzleData(e,a),Bo=!0}L=!!ko.getFinishTs(e)})):"replay"===o&&J.push(setInterval((()=>{const t=O();if(v.requesting)return void(v.lastRealTs=t);if(v.logPointer+1>=v.log.length)return v.lastRealTs=t,void(async e=>{const t=await b(e);v.log=v.log.slice(v.logPointer),v.logPointer=0,v.log.push(...t.log),t.log.length=v.log.length){v.final&&ee();break}const n=v.log[t],l=v.gameStartTs+n[n.length-1];if(l>o)break;const a=n.slice();if(a[0]===zt){const t=a[1];ko.addPlayer(e,t,l),Bo=!0}else if(a[0]===Tt){const t=ko.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (update player) ]";ko.addPlayer(e,t,l),Bo=!0}else if(a[0]===Pt){const t=ko.getPlayerIdByIndex(e,a[1]);if(!t)throw"[ 2021-05-17 player not found (handle input) ]";const n=a[2];ko.handleInput(e,t,n,l),Bo=!0}v.logPointer=t}v.lastRealTs=t,v.lastGameTs=o,V()}),50));let ne=null;return te=(e=>{let t=!1;const n=e.fps||60,o=e.slow||1,l=e.update,a=e.render,i=window.requestAnimationFrame,s=1/n,r=o*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,l(s);a(c/o),u=d,t||i(p)};return i(p),{stop:()=>{t=!0}}})({update:()=>{U.createKeyEvents();for(const n of U.consumeAll())if("play"===o){const o=n[0];if(o===It){const e=n[1],t=n[2],o=N.worldDimToViewport({w:e,h:t});Bo=!0,N.move(o.w,o.h)}else if(o===Mt){if(ne&&!ko.getFirstOwnedPiece(e,t)){const e={x:n[1],y:n[2]},t=N.worldToViewport(e),o=Math.round(t.x-ne.x),l=Math.round(t.y-ne.y);Bo=!0,N.move(o,l),ne=t}}else if(o===Nt)K(n[1]);else if(o===_t){const e={x:n[1],y:n[2]};ne=N.worldToViewport(e),Z(!0)}else if(o===Et)ne=null,Z(!1);else if(o===Dt){const e={x:n[1],y:n[2]};Bo=!0,N.zoom("in",N.worldToViewport(e))}else if(o===Ot){const e={x:n[1],y:n[2]};Bo=!0,N.zoom("out",N.worldToViewport(e))}else o===Rt?a.togglePreview():o===Vt&&a.toggleSoundsEnabled();const l=x();ko.handleInput(e,t,n,l,(e=>{j()&&s.play()})).length>0&&(Bo=!0),en.sendClientEvent(n)}else if("replay"===o){const e=n[0];if(e===It){const e=n[1],t=n[2];Bo=!0,N.move(e,t)}else if(e===Mt){if(ne){const e={x:n[1],y:n[2]},t=N.worldToViewport(e),o=Math.round(t.x-ne.x),l=Math.round(t.y-ne.y);Bo=!0,N.move(o,l),ne=t}}else if(e===_t){const e={x:n[1],y:n[2]};ne=N.worldToViewport(e)}else if(e===Et)ne=null;else if(e===Dt){const e={x:n[1],y:n[2]};Bo=!0,N.zoom("in",N.worldToViewport(e))}else if(e===Ot){const e={x:n[1],y:n[2]};Bo=!0,N.zoom("out",N.worldToViewport(e))}else e===Rt&&a.togglePreview()}L=!!ko.getFinishTs(e),F()&&(D.update(),Bo=!0)},render:async()=>{if(!Bo)return;const n=x();let l,i,s;window.DEBUG&&En(0),B.fillStyle=W(),B.fillRect(0,0,w.width,w.height),window.DEBUG&&Mn("clear done"),l=N.worldToViewportRaw(I),i=N.worldDimToViewportRaw(_),B.fillStyle="rgba(255, 255, 255, .3)",B.fillRect(l.x,l.y,i.w,i.h),window.DEBUG&&Mn("board done");const r=ko.getPiecesSortedByZIndex(e);window.DEBUG&&Mn("get tiles done"),i=N.worldDimToViewportRaw(E);for(const e of r)(-1===e.owner?Do:Oo)&&(s=M[e.idx],l=N.worldToViewportRaw({x:k+e.pos.x,y:k+e.pos.y}),B.drawImage(s,0,0,s.width,s.height,l.x,l.y,i.w,i.h));window.DEBUG&&Mn("tiles done");const d=[];for(const a of ko.getActivePlayers(e,n))c=a,("replay"===o||c.id!==t)&&(s=await f(a),l=N.worldToViewport(a),B.drawImage(s,l.x-g,l.y-m),d.push([`${a.name} (${a.points})`,l.x,l.y+h]));var c;B.fillStyle="white",B.textAlign="center";for(const[e,t,o]of d)B.fillText(e,t,o);window.DEBUG&&Mn("players done"),a.setActivePlayers(ko.getActivePlayers(e,n)),a.setIdlePlayers(ko.getIdlePlayers(e,n)),a.setPiecesDone(ko.getFinishedPiecesCount(e)),window.DEBUG&&Mn("HUD done"),F()&&D.render(),Bo=!1}}),{setHotkeys:e=>{U.setHotkeys(e)},onBgChange:e=>{localStorage.setItem("bg_color",e),U.addEvent([Bt,e])},onColorChange:e=>{localStorage.setItem("player_color",e),U.addEvent([Nt,e])},onNameChange:e=>{localStorage.setItem("player_name",e),U.addEvent([Ut,e])},onSoundsEnabledChange:e=>{localStorage.setItem("sound_enabled",e?"1":"0")},replayOnSpeedUp:()=>{v.speedIdx+1{v.speedIdx>=1&&(v.speedIdx--,X())},replayOnPauseToggle:()=>{v.paused=!v.paused,X()},previewImageUrl:R,player:{background:W(),color:q(),name:ko.getPlayerName(e,t)||localStorage.getItem("player_name")||"anon",soundsEnabled:j()},disconnect:en.disconnect,connect:C,unload:()=>{ee(),te&&te.stop()}}}var Uo=e({name:"game",components:{PuzzleStatus:gt,Scores:rt,SettingsOverlay:mt,PreviewOverlay:bt,ConnectionOverlay:tn,HelpOverlay:rn},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 No(`${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 Ro={id:"game"},Vo={class:"menu"},$o={class:"tabs"},Go=s("🧩 Puzzles");Uo.render=function(e,l,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"),w=a("scores");return i(),t("div",Ro,[p(n(u,{onBgclick:l[1]||(l[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":l[2]||(l[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[C,"settings"===e.overlay]]),p(n(g,{onBgclick:l[3]||(l[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[C,"preview"===e.overlay]]),p(n(h,{onBgclick:l[4]||(l[4]=t=>e.toggle("help",!0))},null,512),[[C,"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",Vo,[n("div",$o,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[Go])),_:1}),n("div",{class:"opener",onClick:l[5]||(l[5]=t=>e.toggle("preview",!1))},"πŸ–ΌοΈ Preview"),n("div",{class:"opener",onClick:l[6]||(l[6]=t=>e.toggle("settings",!0))},"πŸ› οΈ Settings"),n("div",{class:"opener",onClick:l[7]||(l[7]=t=>e.toggle("help",!0))},"ℹ️ Help")])]),n(w,{activePlayers:e.activePlayers,idlePlayers:e.idlePlayers},null,8,["activePlayers","idlePlayers"])])};var Lo=e({name:"replay",components:{PuzzleStatus:gt,Scores:rt,SettingsOverlay:mt,PreviewOverlay:bt,HelpOverlay:rn},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=>{},replayOnSpeedUp:()=>{},replayOnSpeedDown:()=>{},replayOnPauseToggle:()=>{},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 No(`${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 Fo={id:"replay"},jo={class:"menu"},Wo={class:"tabs"},qo=s("🧩 Puzzles");Lo.render=function(e,l,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"),w=a("scores");return i(),t("div",Fo,[p(n(g,{onBgclick:l[1]||(l[1]=t=>e.toggle("settings",!0)),modelValue:e.g.player,"onUpdate:modelValue":l[2]||(l[2]=t=>e.g.player=t)},null,8,["modelValue"]),[[C,"settings"===e.overlay]]),p(n(h,{onBgclick:l[3]||(l[3]=t=>e.toggle("preview",!1)),img:e.g.previewImageUrl},null,8,["img"]),[[C,"preview"===e.overlay]]),p(n(m,{onBgclick:l[4]||(l[4]=t=>e.toggle("help",!0))},null,512),[[C,"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:l[5]||(l[5]=t=>e.g.replayOnSpeedUp())},"⏫"),n("button",{class:"btn",onClick:l[6]||(l[6]=t=>e.g.replayOnSpeedDown())},"⏬"),n("button",{class:"btn",onClick:l[7]||(l[7]=t=>e.g.replayOnPauseToggle())},"⏸️")])])),_:1},8,["finished","duration","piecesDone","piecesTotal"]),n("div",jo,[n("div",Wo,[n(f,{class:"opener",to:{name:"index"},target:"_blank"},{default:o((()=>[qo])),_:1}),n("div",{class:"opener",onClick:l[8]||(l[8]=t=>e.toggle("preview",!1))},"πŸ–ΌοΈ Preview"),n("div",{class:"opener",onClick:l[9]||(l[9]=t=>e.toggle("settings",!0))},"πŸ› οΈ Settings"),n("div",{class:"opener",onClick:l[10]||(l[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=k({history:A(),routes:[{name:"index",path:"/",component:F},{name:"new-game",path:"/new-game",component:Xe},{name:"game",path:"/g/:id",component:Uo},{name:"replay",path:"/replay/:id",component:Lo}]});n.beforeEach(((e,t)=>{t.name&&document.documentElement.classList.remove(`view-${String(t.name)}`),document.documentElement.classList.add(`view-${String(e.name)}`)}));const o=S(z);o.config.globalProperties.$config=t,o.config.globalProperties.$clientId=function(){let e=localStorage.getItem("ID");return e||(e=Ke.uniqId(),localStorage.setItem("ID",e)),e}(),o.use(n),o.mount("#app")})(); diff --git a/build/public/index.html b/build/public/index.html index 2506ca1..7fe4126 100644 --- a/build/public/index.html +++ b/build/public/index.html @@ -4,9 +4,9 @@ 🧩 jigsaw.hyottoko.club - + - +
diff --git a/src/frontend/components/NewGameDialog.vue b/src/frontend/components/NewGameDialog.vue index c2fb724..d3df7fb 100644 --- a/src/frontend/components/NewGameDialog.vue +++ b/src/frontend/components/NewGameDialog.vue @@ -132,6 +132,16 @@ export default defineComponent({ height: 90%; width: 80%; } +@media (max-width: 1400px) { + .new-game-dialog .overlay-content { + grid-template-columns: auto; + grid-template-rows: 1fr min-content min-content; + grid-template-areas: + "image" + "settings" + "buttons"; + } +} .new-game-dialog .area-image { grid-area: image; margin: 20px; diff --git a/src/frontend/components/NewImageDialog.vue b/src/frontend/components/NewImageDialog.vue index c9db112..1f3de7d 100644 --- a/src/frontend/components/NewImageDialog.vue +++ b/src/frontend/components/NewImageDialog.vue @@ -7,7 +7,12 @@ gallery", if possible!
-
+
X @@ -15,7 +20,7 @@ gallery", if possible!
@@ -52,10 +57,13 @@ gallery", if possible! @@ -132,6 +183,16 @@ export default defineComponent({ height: 90%; width: 80%; } +@media (max-width: 1400px) { + .new-image-dialog .overlay-content { + grid-template-columns: auto; + grid-template-rows: 1fr min-content min-content; + grid-template-areas: + "image" + "settings" + "buttons"; + } +} .new-image-dialog .area-image { grid-area: image; @@ -141,9 +202,15 @@ export default defineComponent({ align-content: center; display: grid; text-align: center; - border: dashed 6px; + border: solid 6px; position: relative; } +.new-image-dialog .area-image.droppable { + border: dashed 6px; +} +.area-image * { + pointer-events: none; +} .new-image-dialog .area-image .has-image { position: relative; width: 100%;