diff --git a/dist/index.html b/dist/index.html index f8d7adf..c75939a 100644 --- a/dist/index.html +++ b/dist/index.html @@ -1 +1 @@ -toneapi_webclient
\ No newline at end of file +toneapi_webclient
\ No newline at end of file diff --git a/dist/js/app.a58f4a45.js b/dist/js/app.a58f4a45.js new file mode 100644 index 0000000..2b9b019 --- /dev/null +++ b/dist/js/app.a58f4a45.js @@ -0,0 +1,2 @@ +(function(){"use strict";var e={3870:function(e,t,r){var s=r(3862),a=r(3396);const i=(0,a.uE)('
',4);function l(e,t,r,s,l,o){const n=(0,a.up)("router-link"),h=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)(a.HY,null,[(0,a._)("header",null,[(0,a._)("nav",null,[i,(0,a.Wm)(n,{to:"/",class:"navbar-element"},{default:(0,a.w5)((()=>[(0,a.Uk)("Players")])),_:1})])]),(0,a.Wm)(h)],64)}r(7658);var o=r(1020),n=r(5130);function h(e){return Object.fromEntries(Object.entries(e).filter((e=>void 0!==e[1]&&null!==e[1])))}function p(e,t){try{return e=h(e),t=h(t),n.deepStrictEqual(e,t),!0}catch{return!1}}const d=(0,o.Q_)("kill",{state:()=>({servers:[],players:[],weapons:[],maps:[],gamemodes:[],hosts:{}}),getters:{getPlayerList:e=>t=>e.players.find((e=>p(e.filter,t))),getWeaponList:e=>t=>e.weapons.find((e=>p(e.filter,t))),getServerList:e=>t=>e.servers.find((e=>p(e.filter,t)))},actions:{async fetchPlayers(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2/client/players?"+new URLSearchParams(e)),r=await t.json(),s=this.players.find((t=>p(t.filter,e)));if(!s)return this.players.push({filter:e,data:r});s.data=r},async fetchWeapons(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2/client/weapons?"+new URLSearchParams(e)),r=await t.json(),s=this.weapons.find((t=>p(t.filter,e)));if(!s)return this.weapons.push({filter:e,data:r});s.data=r},async fetchServers(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2/client/servers?"+new URLSearchParams(e)),r=await t.json(),s=this.servers.find((t=>p(t.filter,e)));if(!s)return this.servers.push({filter:e,data:r});s.data=r}}});var c=(0,a.aZ)({setup(e,t){const r=d();r.fetchPlayers({}),r.fetchServers({}),r.fetchWeapons({})}}),u=r(89);const g=(0,u.Z)(c,[["render",l]]);var y=g,f=r(2483);const m={id:"filters"},v={id:"playerView"};function b(e,t,r,s,i,l){const o=(0,a.up)("VueMultiselect"),n=(0,a.up)("PlayerList"),h=(0,a.up)("PlayerChart"),p=(0,a.up)("WeaponChart");return(0,a.wg)(),(0,a.iD)(a.HY,null,[(0,a._)("div",m,[(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Select server",modelValue:e.model.server,"onUpdate:modelValue":t[0]||(t[0]=t=>e.model.server=t),options:e.groupedServers,"group-values":"servers",group_label:"id","group-select":!1,"allow-empty":!0,multiple:!1,"custom-label":e=>e.name,"track-by":"name",label:"name"},null,8,["modelValue","options","custom-label"]),(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Select weapon",modelValue:e.model.weapon,"onUpdate:modelValue":t[1]||(t[1]=t=>e.model.weapon=t),options:e.sortedWeaponList,"allow-empty":!0},null,8,["modelValue","options"]),(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Search player",modelValue:e.playerHighlighted,"onUpdate:modelValue":t[2]||(t[2]=t=>e.playerHighlighted=t),options:e.sortedPlayerList,"allow-empty":!0,"custom-label":t=>e.players[t]?.username},null,8,["modelValue","options","custom-label"])]),(0,a._)("div",v,[(0,a.Wm)(n,{filters:e.filters,onHighlightPlayer:t[3]||(t[3]=t=>e.playerHighlighted=t),playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"]),(0,a.Wm)(h,{filters:e.filters,onHighlightPlayer:t[4]||(t[4]=t=>e.playerHighlighted=t),playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"]),(0,a.Wm)(p,{filters:{player:e.playerHighlighted,...e.filters},playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"])])],64)}var w=r(7139);const k=e=>((0,a.dD)("data-v-33cdd346"),e=e(),(0,a.Cn)(),e),L={class:"playerHeaders"},P=k((()=>(0,a._)("span",null,null,-1))),_=["onClick"];function H(e,t,r,s,i,l){return(0,a.wg)(),(0,a.iD)("div",{class:"playerTable",onKeydown:t[6]||(t[6]=(...t)=>e.selectNextPlayer&&e.selectNextPlayer(...t)),tabindex:"0"},[(0,a._)("div",L,[P,(0,a._)("span",{onClick:t[0]||(t[0]=t=>e.sortPlayerList("username")),class:(0,w.C_)("username"==e.sortingData.argument?"selected":"")},"Username",2),(0,a._)("span",{onClick:t[1]||(t[1]=t=>e.sortPlayerList("kills")),class:(0,w.C_)("kills"==e.sortingData.argument?"selected":"")},"K",2),(0,a._)("span",{onClick:t[2]||(t[2]=t=>e.sortPlayerList("deaths")),class:(0,w.C_)("deaths"==e.sortingData.argument?"selected":"")},"D",2),(0,a._)("span",{onClick:t[3]||(t[3]=t=>e.sortPlayerList("k/d")),class:(0,w.C_)("k/d"==e.sortingData.argument?"selected":"")},"K/D",2),(0,a._)("span",{onClick:t[4]||(t[4]=t=>e.sortPlayerList("max_distance")),class:(0,w.C_)("max_distance"==e.sortingData.argument?"selected":"")},"max distance",2),(0,a._)("span",{onClick:t[5]||(t[5]=t=>e.sortPlayerList("avg_distance")),class:(0,w.C_)("avg_distance"==e.sortingData.argument?"selected":"")},"average distance",2)]),((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)(e.playerIdList,((t,r)=>((0,a.wg)(),(0,a.iD)("div",{class:(0,w.C_)("playerRow "+(t===e.$props.playerHighlighted?"selected":"")),key:t,onClick:r=>e.$emit("highlightPlayer",t),ref_for:!0,ref:"player:"+t},[(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(r+1),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].username),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].kills),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].deaths),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(Math.round(e.players[t].kills/Math.max(1,e.players[t].deaths)*100)/100),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].max_distance),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(Math.round(100*(e.players[t].total_distance/e.players[t].kills||0))/100),1)])],10,_)))),128))],32)}var I=(0,a.aZ)({props:{filters:{type:Object,default:()=>({})},playerHighlighted:String},emits:["highlightPlayer"],data(){return{sortingData:{direction:-1,argument:"kills"},playerIdList:[],store:d()}},computed:{players(){const{player:e,...t}=this.filters;return this.store.getPlayerList(t)?.data||{}}},watch:{players:{handler(e){e&&(this.playerIdList=[],this.sortingData.direction*=-1,this.playerIdList=Object.keys(e),this.sortPlayerList(this.sortingData.argument),this.playerIdList=this.playerIdList.slice(0,500))},immediate:!0},playerHighlighted(e){const t=this.$refs["player:"+e];t&&t[0]&&t[0].scrollIntoView({behavior:"smooth",block:"center"})}},updated(){const e=this.$refs["player:"+this.$props.playerHighlighted];e&&e[0]&&e[0].scrollIntoView({behavior:"smooth",block:"center"})},methods:{sortPlayerList(e){e===this.sortingData.argument?this.sortingData.direction*=-1:"username"===e&&(this.sortingData.direction=1),this.sortingData.argument=e,this.playerIdList.sort(((t,r)=>{if(!this.players)return 0;let s,a;return"k/d"===e?(s=this.players[t].kills/Math.max(1,this.players[t].deaths),a=this.players[r].kills/Math.max(1,this.players[r].deaths)):"avg_distance"===e?(s=this.players[t].total_distance/this.players[t].kills||0,a=this.players[r].total_distance/this.players[r].kills||0):(s=this.players[t][e],a=this.players[r][e]),void 0===s||void 0===a?0:sa?1*this.sortingData.direction:0}))},selectNextPlayer(e){const t={Home:-1/0,End:1/0,PageDown:100,PageUp:-100,ArrowUp:-1,ArrowDown:1,ArrowRight:10,ArrowLeft:-10};if(!this.$props.playerHighlighted)return;if(!Object.keys(t).includes(e.key))return;e.preventDefault();const r=this.playerIdList.indexOf(this.$props.playerHighlighted);let s=r+t[e.key];s>=this.playerIdList.length&&(s=this.playerIdList.length-1),s<0&&(s=0),this.$emit("highlightPlayer",this.playerIdList[s])}}});const C=(0,u.Z)(I,[["render",H],["__scopeId","data-v-33cdd346"]]);var x=C;const O={class:"playerChart",ref:"container"};function $(e,t,r,s,i,l){const o=(0,a.up)("Scatter");return(0,a.wg)(),(0,a.iD)("div",O,[(0,a.Wm)(o,{data:e.chart,options:e.chartOptions},null,8,["data","options"])],512)}var D=r(3254),W=r(9152),V=r(1131),j=r(5866);D.kL.register(D.f$,D.od,D.jn,D.u,D.De,W.Z,V.Z);var S=(0,a.aZ)({name:"PlayerChart",props:{filters:Object,playerHighlighted:String},data:()=>({store:d(),refreshColors:0}),emits:["highlightPlayer"],components:{Scatter:j.bp},mounted(){this.refreshColors++},computed:{colors(){this.refreshColors;const e={};if(this.$refs.container){const t=getComputedStyle(this.$refs.container);e.fg=t.getPropertyValue("--foreground"),e.bg=t.getPropertyValue("--bg-color"),e.orange=t.getPropertyValue("--orange"),e.cyan=t.getPropertyValue("--cyan"),e.currentLine=t.getPropertyValue("--current-line")}else e.fg="#ffffff";return e},chart(){return{datasets:[{label:"Players",labels:this.playerIdList||[],borderColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?this.colors.orange:this.colors.cyan,backgroundColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?this.colors.orange:this.colors.cyan,pointRadius:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?20:1,pointStyle:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?"crossRot":"circle",hoverRadius:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?30:4,data:this.playerIdList.map((e=>({y:this.players[e].kills,x:this.players[e].deaths})))}]}},chartOptions(){this.$props.playerHighlighted;let e=0,t=0;if(this.players){const r=Math.max(...Object.values(this.players).map((e=>e.deaths))),s=Math.max(...Object.values(this.players).map((e=>e.kills)));s>r?(e=r,t=r/s*s):(t=s,e=s/r*r)}return{responsive:!0,maintainAspectRatio:!1,animation:{duration:500},layout:{autoPadding:!1},scales:{y:{title:{text:"Kills",display:!0,color:this.colors.fg},ticks:{color:this.colors.fg}},x:{title:{text:"Deaths",display:!0,color:this.colors.fg},ticks:{color:this.colors.fg}}},plugins:{tooltip:{callbacks:{label:e=>{let t;return t=this.players?this.players[e.dataset.labels[e.dataIndex]].username:e.dataset.labels[e.dataIndex],t+=" ("+e.parsed.y+" kills "+e.parsed.x+" deaths)",t}}},annotation:{annotations:{line:{type:"line",yMin:0,xMin:0,yMax:t,xMax:e,borderWidth:2,borderColor:this.colors.orange,borderDash:[1,5]}}},legend:{display:!1},datalabels:{formatter:(e,t)=>this.players[this.playerIdList[t.dataIndex]].username,backgroundColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?this.colors.orange:null,borderColor:this.colors.fg,borderWidth:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?1:0,borderRadius:5,display:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?"true":"auto",align:-45,anchor:"end",clamp:!0,color:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?this.colors.bg:this.colors.fg}},onClick:(e,t)=>{this.$emit("highlightPlayer",t.length>0?this.playerIdList[t[0].index]:void 0)},onHover:(e,t)=>{e.native.target&&(e.native.target.style.cursor=t[0]?"pointer":"default")}}},players(){const e=this.store.getPlayerList(this.filters||{})?.data;if(!e)return{};const t=Object.entries(e).sort(((e,t)=>e[1].killst[1].kills?-1:0)).slice(0,200);return Object.fromEntries(t)},playerIdList(){return Object.keys(this.players)}}});const M=(0,u.Z)(S,[["render",$],["__scopeId","data-v-a55781c4"]]);var Z=M;const R={class:"weaponChart",ref:"container"};function U(e,t,r,s,i,l){const o=(0,a.up)("Doughnut");return(0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(o,{data:e.chart,options:e.chartOptions},null,8,["data","options"])],512)}D.kL.register(D.qi,D.u,D.De,V.Z);var z=(0,a.aZ)({name:"PlayerChart",props:{filters:Object,playerHighlighted:String},emits:["highlightPlayer"],components:{Doughnut:j.$I},mounted(){this.refreshColors++},data:()=>({store:d(),refreshColors:0}),computed:{colors(){this.refreshColors;const e={};if(this.$refs.container){const t=getComputedStyle(this.$refs.container);e.fg=t.getPropertyValue("--foreground"),e.bg=t.getPropertyValue("--bg-color"),e.orange=t.getPropertyValue("--orange"),e.cyan=t.getPropertyValue("--cyan"),e.yellow=t.getPropertyValue("--yellow"),e.green=t.getPropertyValue("--green"),e.purple=t.getPropertyValue("--purple"),e.red=t.getPropertyValue("--red"),e.pink=t.getPropertyValue("--pink"),e.currentLine=t.getPropertyValue("--current-line")}else e.fg="#ffffff";return e},chart(){const e=["cyan","green","orange","pink","purple","red","yellow"],t={datasets:[{label:"Weapons",labels:this.sortedWeaponList||[],borderColor:()=>this.colors.fg,backgroundColor:t=>this.colors[e[3*t.dataIndex%e.length]],data:[]}]};return this.sortedWeaponList?(t.datasets[0].data=this.sortedWeaponList.map((e=>this.weapons?this.weapons[e].kills:0)),t):t},chartOptions(){this.$props.playerHighlighted;const e={responsive:!0,maintainAspectRatio:!0,animation:{duration:500},layout:{autoPadding:!1},plugins:{datalabels:{formatter:(e,t)=>this.sortedWeaponList[t.dataIndex],backgroundColor:e=>e.dataset.backgroundColor(e),borderColor:this.colors.fg,borderRadius:25,borderWidth:2,color:this.colors.bg,display:e=>e.dataIndex===e.dataset.labels.length-1||"auto",padding:6},tooltip:{callbacks:{label:e=>{let t;return t=this.sortedWeaponList?this.sortedWeaponList[e.dataIndex]:e.dataset.labels[e.dataIndex],t+=" ("+this.weapons[t].kills+" kills)",t}}}}};return e},weapons(){const{weapon:e,...t}=this.filters||{},r=this.store.getWeaponList(t)?.data;return r||(this.store.fetchWeapons(t),{})},sortedWeaponList(){if(!this.weapons)return[];const e=Object.keys(this.weapons);return e.sort(((e,t)=>Number(this.weapons[e].kills)Number(this.weapons[t].kills)?1:0)),e}}});const A=(0,u.Z)(z,[["render",U],["__scopeId","data-v-673fd0b6"]]);var N=A,E=r(6368),T=(0,a.aZ)({name:"PlayerView",components:{VueMultiselect:E.ZP,PlayerList:x,PlayerChart:Z,WeaponChart:N},data(){return{model:{server:void 0,weapon:void 0},filters:{},store:d(),playerHighlighted:void 0}},computed:{servers(){const{server:e,player:t,...r}=this.filters,s=this.store.getServerList(r)?.data;return s||(this.store.fetchServers(r),{})},groupedServers(){const e=[];return Object.entries(this.servers).forEach((t=>{e.find((e=>e.id===t[1].host+"sfdsdfsd"))||e.push({id:t[1].host+"sfdsdfsd",servers:[]}),e.find((e=>e.id===t[1].host+"sfdsdfsd"))?.servers.push({name:t[0],...t[1]})})),e},weapons(){const{weapon:e,player:t,...r}=this.filters,s=this.store.getWeaponList(r)?.data;return s||(this.store.fetchWeapons(r),{})},players(){const{player:e,...t}=this.filters,r=this.store.getPlayerList(t)?.data;return r||(this.store.fetchPlayers(t),{})},sortedWeaponList(){if(!this.weapons)return[];const e=Object.keys(this.weapons);return e.sort()},sortedServerList(){if(!this.servers)return[];const e=Object.keys(this.servers);return e.sort()},sortedPlayerList(){if(!this.players)return[];const e=Object.keys(this.players);return e.sort(((e,t)=>this.players?this.players[e].usernamethis.players[t].username?1:0:0))}},watch:{model:{handler(e){this.filters.server=e.server?.name,this.filters.weapon=e.weapon},deep:!0}}});const K=(0,u.Z)(T,[["render",b],["__scopeId","data-v-8bebdda4"]]);var Y=K;const q=[{path:"/",name:"home",component:Y}],B=(0,f.p7)({history:(0,f.PO)("/ToneAPI_webclient/"),routes:q});var F=B;const G=(0,o.WB)();(0,s.ri)(y).use(G).use(F).mount("#app")}},t={};function r(s){var a=t[s];if(void 0!==a)return a.exports;var i=t[s]={exports:{}};return e[s](i,i.exports,r),i.exports}r.m=e,function(){var e=[];r.O=function(t,s,a,i){if(!s){var l=1/0;for(p=0;p=i)&&Object.keys(r.O).every((function(e){return r.O[e](s[n])}))?s.splice(n--,1):(o=!1,i0&&e[p-1][2]>i;p--)e[p]=e[p-1];e[p]=[s,a,i]}}(),function(){r.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return r.d(t,{a:t}),t}}(),function(){r.d=function(e,t){for(var s in t)r.o(t,s)&&!r.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})}}(),function(){r.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){var e={143:0};r.O.j=function(t){return 0===e[t]};var t=function(t,s){var a,i,l=s[0],o=s[1],n=s[2],h=0;if(l.some((function(t){return 0!==e[t]}))){for(a in o)r.o(o,a)&&(r.m[a]=o[a]);if(n)var p=n(r)}for(t&&t(s);hTONE API
\", 4)\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_router_link = _resolveComponent(\"router-link\")!\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(_Fragment, null, [\n _createElementVNode(\"header\", null, [\n _createElementVNode(\"nav\", null, [\n _hoisted_1,\n _createVNode(_component_router_link, {\n to: \"/\",\n class: \"navbar-element\"\n }, {\n default: _withCtx(() => [\n _createTextVNode(\"Players\")\n ]),\n _: 1\n })\n ])\n ]),\n _createVNode(_component_router_view)\n ], 64))\n}","import { defineStore } from 'pinia'\r\nimport * as assert from 'assert'\r\n\r\nfunction removeNullEntries (a:any) {\r\n return Object.fromEntries(Object.entries(a).filter(e => e[1] !== undefined && e[1] !== null))\r\n}\r\nfunction objectEqual (a:any, b:any) {\r\n try {\r\n a = removeNullEntries(a)\r\n b = removeNullEntries(b)\r\n assert.deepStrictEqual(a, b)\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\nexport interface Filters {\r\n server?: string;\r\n player?: string;\r\n weapon?: string;\r\n host?: string;\r\n map?: string;\r\n gamemode?: string;\r\n}\r\n\r\nexport interface Kill {\r\n deaths: number;\r\n kills: number;\r\n // eslint-disable-next-line camelcase\r\n max_distance: number;\r\n // eslint-disable-next-line camelcase\r\n total_distance: number;\r\n}\r\nexport interface KillData {\r\n filter: Filters;\r\n data: { [key: string]: T };\r\n}\r\n\r\nexport interface Player extends Kill {\r\n username: string;\r\n // eslint-disable-next-line camelcase\r\n deaths_while_equipped?: number;\r\n}\r\n\r\nexport interface Weapon extends Kill {\r\n // eslint-disable-next-line camelcase\r\n deaths_while_equipped: number;\r\n}\r\n\r\nexport interface Server extends Kill {\r\n host: number;\r\n}\r\n\r\n// define your typings for the store state\r\nexport interface State {\r\n servers: KillData[];\r\n players: KillData[];\r\n weapons: KillData[];\r\n maps: KillData[];\r\n gamemodes: KillData[];\r\n hosts: { [key: number]: string };\r\n}\r\n\r\nexport const useKillStore = defineStore('kill', {\r\n state: (): State => ({\r\n servers: [],\r\n players: [],\r\n weapons: [],\r\n maps: [],\r\n gamemodes: [],\r\n hosts: {}\r\n }),\r\n getters: {\r\n getPlayerList: (state) => (filters: Filters) => state.players.find((e) => objectEqual(e.filter, filters)),\r\n getWeaponList: (state) => (filters: Filters) => state.weapons.find((e) => objectEqual(e.filter, filters)),\r\n getServerList: (state) => (filters: Filters) => state.servers.find((e) => objectEqual(e.filter, filters))\r\n },\r\n actions: {\r\n async fetchPlayers (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2/client/players?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.players.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.players.push({ filter, data })\r\n entry.data = data\r\n },\r\n async fetchWeapons (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2/client/weapons?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.weapons.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.weapons.push({ filter, data })\r\n entry.data = data\r\n },\r\n async fetchServers (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2/client/servers?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.servers.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.servers.push({ filter, data })\r\n entry.data = data\r\n }\r\n }\r\n})\r\n","\r\nimport { Player, Weapon, Server, useKillStore } from '@/stores/kill'\r\nimport { defineComponent } from 'vue'\r\n\r\nexport default defineComponent({\r\n setup (props, ctx) {\r\n const store = useKillStore()\r\n store.fetchPlayers({})\r\n store.fetchServers({})\r\n store.fetchWeapons({})\r\n }\r\n})\r\n","import { render } from \"./App.vue?vue&type=template&id=a4a5fcd4&ts=true\"\nimport script from \"./App.vue?vue&type=script&lang=ts\"\nexport * from \"./App.vue?vue&type=script&lang=ts\"\n\nimport \"./App.vue?vue&type=style&index=0&id=a4a5fcd4&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-8bebdda4\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = { id: \"filters\" }\nconst _hoisted_2 = { id: \"playerView\" }\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_VueMultiselect = _resolveComponent(\"VueMultiselect\")!\n const _component_PlayerList = _resolveComponent(\"PlayerList\")!\n const _component_PlayerChart = _resolveComponent(\"PlayerChart\")!\n const _component_WeaponChart = _resolveComponent(\"WeaponChart\")!\n\n return (_openBlock(), _createElementBlock(_Fragment, null, [\n _createElementVNode(\"div\", _hoisted_1, [\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Select server\",\n modelValue: _ctx.model.server,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = ($event: any) => ((_ctx.model.server) = $event)),\n options: _ctx.groupedServers,\n \"group-values\": \"servers\",\n group_label: \"id\",\n \"group-select\": false,\n \"allow-empty\": true,\n multiple: false,\n \"custom-label\": ((e) => e.name),\n \"track-by\": \"name\",\n label: \"name\"\n }, null, 8, [\"modelValue\", \"options\", \"custom-label\"]),\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Select weapon\",\n modelValue: _ctx.model.weapon,\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = ($event: any) => ((_ctx.model.weapon) = $event)),\n options: _ctx.sortedWeaponList,\n \"allow-empty\": true\n }, null, 8, [\"modelValue\", \"options\"]),\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Search player\",\n modelValue: _ctx.playerHighlighted,\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = ($event: any) => ((_ctx.playerHighlighted) = $event)),\n options: _ctx.sortedPlayerList,\n \"allow-empty\": true,\n \"custom-label\": ((e) => _ctx.players[e]?.username)\n }, null, 8, [\"modelValue\", \"options\", \"custom-label\"])\n ]),\n _createElementVNode(\"div\", _hoisted_2, [\n _createVNode(_component_PlayerList, {\n filters: _ctx.filters,\n onHighlightPlayer: _cache[3] || (_cache[3] = ($event: any) => (_ctx.playerHighlighted = $event)),\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"]),\n _createVNode(_component_PlayerChart, {\n filters: _ctx.filters,\n onHighlightPlayer: _cache[4] || (_cache[4] = ($event: any) => (_ctx.playerHighlighted = $event)),\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"]),\n _createVNode(_component_WeaponChart, {\n filters: {player: _ctx.playerHighlighted, ..._ctx.filters},\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"])\n ])\n ], 64))\n}","import { createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, toDisplayString as _toDisplayString, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-33cdd346\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = { class: \"playerHeaders\" }\nconst _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"span\", null, null, -1))\nconst _hoisted_3 = [\"onClick\"]\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n return (_openBlock(), _createElementBlock(\"div\", {\n class: \"playerTable\",\n onKeydown: _cache[6] || (_cache[6] = \n//@ts-ignore\n(...args) => (_ctx.selectNextPlayer && _ctx.selectNextPlayer(...args))),\n tabindex: \"0\"\n }, [\n _createElementVNode(\"div\", _hoisted_1, [\n _hoisted_2,\n _createElementVNode(\"span\", {\n onClick: _cache[0] || (_cache[0] = ($event: any) => (_ctx.sortPlayerList('username'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'username' ? 'selected' : '')\n }, \"Username\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[1] || (_cache[1] = ($event: any) => (_ctx.sortPlayerList('kills'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'kills' ? 'selected' : '')\n }, \"K\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[2] || (_cache[2] = ($event: any) => (_ctx.sortPlayerList('deaths'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'deaths' ? 'selected' : '')\n }, \"D\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[3] || (_cache[3] = ($event: any) => (_ctx.sortPlayerList('k/d'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'k/d' ? 'selected' : '')\n }, \"K/D\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[4] || (_cache[4] = ($event: any) => (_ctx.sortPlayerList('max_distance'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'max_distance' ? 'selected' : '')\n }, \"max distance\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[5] || (_cache[5] = ($event: any) => (_ctx.sortPlayerList('avg_distance'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'avg_distance' ? 'selected' : '')\n }, \"average distance\", 2)\n ]),\n (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.playerIdList, (playerId, index) => {\n return (_openBlock(), _createElementBlock(\"div\", {\n class: _normalizeClass('playerRow ' + (playerId === _ctx.$props.playerHighlighted ? 'selected' : '')),\n key: playerId,\n onClick: ($event: any) => (_ctx.$emit('highlightPlayer', playerId)),\n ref_for: true,\n ref: `player:` + playerId\n }, [\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(index+1), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].username), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].kills), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].deaths), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(Math.round(_ctx.players[playerId].kills / Math.max(1, _ctx.players[playerId].deaths) * 100) / 100), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].max_distance), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(Math.round(((_ctx.players[playerId].total_distance / _ctx.players[playerId].kills) || 0) * 100) / 100), 1)\n ])\n ], 10, _hoisted_3))\n }), 128))\n ], 32))\n}","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { useKillStore, Player, Filters } from '@/stores/kill'\r\n\r\nexport default defineComponent({\r\n props: {\r\n filters: { type: Object as PropType, default: () => ({}) },\r\n playerHighlighted: String\r\n },\r\n emits: ['highlightPlayer'],\r\n data () {\r\n return {\r\n sortingData: { direction: -1, argument: 'kills' as keyof Player | 'k/d' | 'avg_distance' },\r\n playerIdList: [] as string[],\r\n store: useKillStore()\r\n }\r\n },\r\n computed: {\r\n players (): { [key: string]: Player } {\r\n const { player: _, ...withoutPlayer } = this.filters\r\n return this.store.getPlayerList(withoutPlayer)?.data || {}\r\n }\r\n },\r\n watch: {\r\n players: {\r\n handler (newval: { [key: string]: Player }): void {\r\n if (!newval) return\r\n this.playerIdList = []\r\n this.sortingData.direction *= -1\r\n this.playerIdList = Object.keys(newval)\r\n this.sortPlayerList(this.sortingData.argument)\r\n this.playerIdList = this.playerIdList.slice(0, 500)\r\n },\r\n immediate: true\r\n },\r\n playerHighlighted (newval) {\r\n const newElement = this.$refs['player:' + newval] as HTMLElement[]\r\n if (newElement && newElement[0]) { newElement[0].scrollIntoView({ behavior: 'smooth', block: 'center' }) }\r\n }\r\n },\r\n updated () {\r\n const element = this.$refs['player:' + this.$props.playerHighlighted] as HTMLElement[]\r\n if (!element || !element[0]) return\r\n element[0].scrollIntoView({ behavior: 'smooth', block: 'center' })\r\n },\r\n methods: {\r\n sortPlayerList (arg: ((keyof Player) | 'k/d' | 'avg_distance')) {\r\n if (arg === this.sortingData.argument) {\r\n this.sortingData.direction *= -1\r\n } else {\r\n if (arg === 'username') {\r\n this.sortingData.direction = 1\r\n }\r\n }\r\n this.sortingData.argument = arg\r\n\r\n this.playerIdList.sort((a: string, b: string) => {\r\n if (!this.players) {\r\n return 0\r\n }\r\n let varA, varB\r\n if (arg === 'k/d') {\r\n varA = this.players[a].kills / Math.max(1, this.players[a].deaths)\r\n varB = this.players[b].kills / Math.max(1, this.players[b].deaths)\r\n } else if (arg === 'avg_distance') {\r\n varA = (this.players[a].total_distance / this.players[a].kills) || 0\r\n varB = (this.players[b].total_distance / this.players[b].kills) || 0\r\n } else {\r\n varA = this.players[a][arg]\r\n varB = this.players[b][arg]\r\n }\r\n if (varA === undefined || varB === undefined) return 0\r\n if (varA < varB) {\r\n return -1 * this.sortingData.direction\r\n }\r\n if (varA > varB) {\r\n return 1 * this.sortingData.direction\r\n }\r\n return 0\r\n })\r\n },\r\n selectNextPlayer (e: KeyboardEvent) {\r\n const values = {\r\n Home: -Infinity,\r\n End: Infinity,\r\n PageDown: 100,\r\n PageUp: -100,\r\n ArrowUp: -1,\r\n ArrowDown: 1,\r\n ArrowRight: 10,\r\n ArrowLeft: -10\r\n } as { [key: string]: number }\r\n if (!this.$props.playerHighlighted) return\r\n if (!Object.keys(values).includes(e.key)) return\r\n e.preventDefault()\r\n const index = this.playerIdList.indexOf(this.$props.playerHighlighted)\r\n let nextIndex = (index + values[e.key])\r\n if (nextIndex >= this.playerIdList.length) nextIndex = this.playerIdList.length - 1\r\n if (nextIndex < 0) nextIndex = 0\r\n this.$emit('highlightPlayer', this.playerIdList[nextIndex])\r\n }\r\n }\r\n\r\n})\r\n","import { render } from \"./PlayerList.vue?vue&type=template&id=33cdd346&scoped=true&ts=true\"\nimport script from \"./PlayerList.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerList.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerList.vue?vue&type=style&index=0&id=33cdd346&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-33cdd346\"]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-a55781c4\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n class: \"playerChart\",\n ref: \"container\"\n}\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_Scatter = _resolveComponent(\"Scatter\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n _createVNode(_component_Scatter, {\n data: _ctx.chart,\n options: _ctx.chartOptions\n }, null, 8, [\"data\", \"options\"])\n ], 512))\n}","\r\nimport {\r\n Chart as ChartJS,\r\n LinearScale,\r\n PointElement,\r\n LineElement,\r\n Tooltip,\r\n Legend,\r\n CoreChartOptions,\r\n PluginChartOptions,\r\n ScaleChartOptions\r\n} from 'chart.js'\r\nimport annotationPlugin from 'chartjs-plugin-annotation'\r\nimport dataLabel from 'chartjs-plugin-datalabels'\r\nimport { useKillStore, Player, Filters } from '@/stores/kill'\r\n\r\nimport { Scatter } from 'vue-chartjs'\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { ChartEvent } from 'chart.js/dist/core/core.plugins'\r\nimport { _DeepPartialObject } from 'chart.js/dist/types/utils'\r\n\r\nChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend, annotationPlugin, dataLabel)\r\n\r\nexport default defineComponent({\r\n name: 'PlayerChart',\r\n props: {\r\n filters: Object as PropType,\r\n playerHighlighted: String\r\n },\r\n data: () => {\r\n return {\r\n store: useKillStore(),\r\n refreshColors: 0\r\n }\r\n },\r\n emits: ['highlightPlayer'],\r\n components: {\r\n Scatter\r\n },\r\n mounted () {\r\n this.refreshColors++\r\n },\r\n computed: {\r\n colors () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.refreshColors\r\n const colors = {} as { [key: string]: string }\r\n if (this.$refs.container) {\r\n const style = getComputedStyle(this.$refs.container as Element)\r\n colors.fg = style.getPropertyValue('--foreground')\r\n colors.bg = style.getPropertyValue('--bg-color')\r\n colors.orange = style.getPropertyValue('--orange')\r\n colors.cyan = style.getPropertyValue('--cyan')\r\n colors.currentLine = style.getPropertyValue('--current-line')\r\n } else {\r\n colors.fg = '#ffffff'\r\n }\r\n return colors\r\n },\r\n chart () {\r\n return {\r\n datasets: [\r\n {\r\n label: 'Players',\r\n labels: this.playerIdList || [] as string[],\r\n borderColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? this.colors.orange : this.colors.cyan,\r\n backgroundColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? this.colors.orange : this.colors.cyan,\r\n pointRadius: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 20 : 1,\r\n pointStyle: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 'crossRot' : 'circle',\r\n hoverRadius: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 30 : 4,\r\n data: this.playerIdList.map((id) => ({ y: this.players[id].kills, x: this.players[id].deaths }))\r\n }\r\n ]\r\n }\r\n },\r\n chartOptions (): _DeepPartialObject & PluginChartOptions<'scatter'> & ScaleChartOptions<'scatter'>> {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.$props.playerHighlighted\r\n let endX = 0\r\n let endY = 0\r\n if (this.players) {\r\n const maxX = Math.max(...Object.values(this.players).map(e => e.deaths))\r\n const maxY = Math.max(...Object.values(this.players).map(e => e.kills))\r\n\r\n if (maxY > maxX) {\r\n endX = maxX\r\n endY = (maxX / maxY) * maxY\r\n } else {\r\n endY = maxY\r\n endX = (maxY / maxX) * maxX\r\n }\r\n }\r\n return {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n animation: { duration: 500 },\r\n layout: { autoPadding: false },\r\n scales: {\r\n y: {\r\n title: {\r\n text: 'Kills',\r\n display: true,\r\n color: this.colors.fg\r\n },\r\n ticks: {\r\n color: this.colors.fg\r\n }\r\n },\r\n x: {\r\n title: {\r\n text: 'Deaths',\r\n display: true,\r\n color: this.colors.fg\r\n },\r\n ticks: {\r\n color: this.colors.fg\r\n }\r\n }\r\n },\r\n plugins: {\r\n tooltip: {\r\n callbacks: {\r\n label: (ctx: any) => {\r\n let label: string\r\n if (!this.players) {\r\n label = ctx.dataset.labels[ctx.dataIndex]\r\n } else {\r\n label = this.players[ctx.dataset.labels[ctx.dataIndex]].username\r\n }\r\n label += ' (' + ctx.parsed.y + ' kills ' + ctx.parsed.x + ' deaths)'\r\n return label\r\n }\r\n }\r\n },\r\n annotation: {\r\n annotations: {\r\n line: {\r\n type: 'line',\r\n yMin: 0,\r\n xMin: 0,\r\n yMax: endY,\r\n xMax: endX,\r\n borderWidth: 2,\r\n borderColor: this.colors.orange,\r\n borderDash: [1, 5]\r\n }\r\n }\r\n },\r\n legend: { display: false },\r\n datalabels: {\r\n formatter: (value: any, context: any) => {\r\n return this.players[this.playerIdList[context.dataIndex]].username\r\n },\r\n backgroundColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? this.colors.orange : null,\r\n borderColor: this.colors.fg,\r\n borderWidth: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? 1 : 0,\r\n borderRadius: 5,\r\n display: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? 'true' : 'auto',\r\n align: -45,\r\n anchor: 'end',\r\n clamp: true,\r\n color: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? this.colors.bg : this.colors.fg\r\n }\r\n },\r\n onClick: (e: ChartEvent, element: any) => {\r\n this.$emit('highlightPlayer', element.length > 0 ? this.playerIdList[element[0].index] : undefined)\r\n },\r\n onHover: (e: any, element: any) => {\r\n if (!e.native.target) return\r\n (e.native.target as HTMLElement).style.cursor = element[0] ? 'pointer' : 'default'\r\n }\r\n }\r\n },\r\n players (): { [key: string]: Player } {\r\n const data = this.store.getPlayerList(this.filters || {})?.data\r\n if (!data) return {}\r\n const cut = Object.entries(data).sort((a, b) => {\r\n if (a[1].kills < b[1].kills) {\r\n return 1\r\n }\r\n if (a[1].kills > b[1].kills) {\r\n return -1\r\n }\r\n return 0\r\n }).slice(0, 200)\r\n return Object.fromEntries(cut)\r\n },\r\n playerIdList (): string[] { return Object.keys(this.players) }\r\n\r\n }\r\n})\r\n","import { render } from \"./PlayerChart.vue?vue&type=template&id=a55781c4&scoped=true&ts=true\"\nimport script from \"./PlayerChart.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerChart.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerChart.vue?vue&type=style&index=0&id=a55781c4&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-a55781c4\"]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-673fd0b6\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n class: \"weaponChart\",\n ref: \"container\"\n}\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_Doughnut = _resolveComponent(\"Doughnut\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n _createVNode(_component_Doughnut, {\n data: _ctx.chart,\n options: _ctx.chartOptions\n }, null, 8, [\"data\", \"options\"])\n ], 512))\n}","\r\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'\r\nimport dataLabel from 'chartjs-plugin-datalabels'\r\nimport { Weapon, Filters, useKillStore } from '@/stores/kill'\r\nimport { Doughnut } from 'vue-chartjs'\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nChartJS.register(ArcElement, Tooltip, Legend, dataLabel)\r\n\r\nexport default defineComponent({\r\n name: 'PlayerChart',\r\n props: {\r\n filters: Object as PropType,\r\n playerHighlighted: String\r\n },\r\n emits: ['highlightPlayer'],\r\n components: {\r\n Doughnut\r\n },\r\n mounted () {\r\n this.refreshColors++\r\n },\r\n data: () => {\r\n return {\r\n store: useKillStore(),\r\n refreshColors: 0\r\n }\r\n },\r\n computed: {\r\n colors () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.refreshColors\r\n const colors = {} as { [key: string]: string }\r\n if (this.$refs.container) {\r\n const style = getComputedStyle(this.$refs.container as Element)\r\n colors.fg = style.getPropertyValue('--foreground')\r\n colors.bg = style.getPropertyValue('--bg-color')\r\n colors.orange = style.getPropertyValue('--orange')\r\n colors.cyan = style.getPropertyValue('--cyan')\r\n colors.yellow = style.getPropertyValue('--yellow')\r\n colors.green = style.getPropertyValue('--green')\r\n colors.purple = style.getPropertyValue('--purple')\r\n colors.red = style.getPropertyValue('--red')\r\n colors.pink = style.getPropertyValue('--pink')\r\n colors.currentLine = style.getPropertyValue('--current-line')\r\n } else {\r\n colors.fg = '#ffffff'\r\n }\r\n return colors\r\n },\r\n chart () {\r\n const colors = [\r\n 'cyan',\r\n 'green',\r\n 'orange',\r\n 'pink',\r\n 'purple',\r\n 'red',\r\n 'yellow'\r\n ]\r\n const chartData = {\r\n datasets: [\r\n {\r\n label: 'Weapons',\r\n labels: this.sortedWeaponList || ([] as string[]),\r\n borderColor: () => this.colors.fg,\r\n backgroundColor: (context: any) => {\r\n return this.colors[\r\n colors[(context.dataIndex * 3) % colors.length]\r\n ]\r\n },\r\n data: [] as number[]\r\n }\r\n ]\r\n }\r\n if (!this.sortedWeaponList) {\r\n return chartData\r\n }\r\n chartData.datasets[0].data = this.sortedWeaponList.map((e) => {\r\n if (!this.weapons) {\r\n return 0\r\n }\r\n return this.weapons[e].kills\r\n })\r\n return chartData\r\n },\r\n chartOptions () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.$props.playerHighlighted\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: true,\r\n animation: { duration: 500 },\r\n layout: { autoPadding: false },\r\n plugins: {\r\n datalabels: {\r\n formatter: (value: any, context: any) => {\r\n return this.sortedWeaponList[context.dataIndex]\r\n },\r\n backgroundColor: (context: any) => {\r\n return context.dataset.backgroundColor(context)\r\n },\r\n borderColor: this.colors.fg,\r\n borderRadius: 25,\r\n borderWidth: 2,\r\n color: this.colors.bg,\r\n display: (context: any) => {\r\n return context.dataIndex === context.dataset.labels.length - 1\r\n ? true\r\n : 'auto'\r\n },\r\n padding: 6\r\n },\r\n tooltip: {\r\n callbacks: {\r\n label: (ctx: any) => {\r\n let label: string\r\n if (!this.sortedWeaponList) {\r\n label = ctx.dataset.labels[ctx.dataIndex]\r\n } else {\r\n label = this.sortedWeaponList[ctx.dataIndex]\r\n }\r\n label += ' (' + this.weapons[label].kills + ' kills)'\r\n return label\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return options\r\n },\r\n weapons (): { [key: string]: Weapon } {\r\n const { weapon: _, ...withoutWeapon } = this.filters || {}\r\n const data = this.store.getWeaponList(withoutWeapon)?.data\r\n if (!data) {\r\n this.store.fetchWeapons(withoutWeapon)\r\n return {}\r\n }\r\n return data\r\n },\r\n sortedWeaponList (): string[] {\r\n if (!this.weapons) return []\r\n const weapons = Object.keys(this.weapons)\r\n weapons.sort((a, b) => {\r\n if (Number(this.weapons[a].kills) < Number(this.weapons[b].kills)) {\r\n return -1\r\n }\r\n if (Number(this.weapons[a].kills) > Number(this.weapons[b].kills)) {\r\n return 1\r\n }\r\n return 0\r\n })\r\n return weapons\r\n }\r\n }\r\n})\r\n","import { render } from \"./WeaponChart.vue?vue&type=template&id=673fd0b6&scoped=true&ts=true\"\nimport script from \"./WeaponChart.vue?vue&type=script&lang=ts\"\nexport * from \"./WeaponChart.vue?vue&type=script&lang=ts\"\n\nimport \"./WeaponChart.vue?vue&type=style&index=0&id=673fd0b6&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-673fd0b6\"]])\n\nexport default __exports__","\r\nimport { Player, Weapon, Server, useKillStore, Filters } from '@/stores/kill'\r\nimport PlayerList from '@/components/PlayerList.vue'\r\nimport PlayerChart from '@/components/PlayerChart.vue'\r\nimport WeaponChart from '@/components/WeaponChart.vue'\r\nimport { defineComponent } from 'vue'\r\nimport VueMultiselect from 'vue-multiselect'\r\nimport 'vue-multiselect/dist/vue-multiselect.css'\r\n\r\nexport default defineComponent({\r\n name: 'PlayerView',\r\n components: {\r\n VueMultiselect, PlayerList, PlayerChart, WeaponChart\r\n },\r\n\r\n data () {\r\n return {\r\n model: { server: undefined, weapon: undefined } as unknown as {weapon:Weapon | Weapon[], server: (Server& {name?:string}) | (Server& {name?:string})[]},\r\n filters: {} as Filters,\r\n store: useKillStore(),\r\n playerHighlighted: undefined\r\n }\r\n },\r\n computed: {\r\n servers (): { [key: string]: Server } {\r\n const { server: _, player: _1, ...withoutServer } = this.filters\r\n const data = this.store.getServerList(withoutServer)?.data\r\n if (!data) {\r\n this.store.fetchServers(withoutServer)\r\n return {}\r\n }\r\n return data\r\n },\r\n groupedServers () {\r\n const hosts = [] as {id:string, servers:(Server& {name?:string})[] }[]\r\n Object.entries(this.servers).forEach((e) => {\r\n if (!hosts.find(host => host.id === e[1].host + 'sfdsdfsd')) hosts.push({ id: e[1].host + 'sfdsdfsd', servers: [] as Server[] })\r\n hosts.find(host => host.id === e[1].host + 'sfdsdfsd')?.servers.push({ name: e[0], ...e[1] })\r\n })\r\n return hosts\r\n },\r\n weapons (): { [key: string]: Weapon } {\r\n const { weapon: _, player: _1, ...withoutWeapons } = this.filters\r\n const data = this.store.getWeaponList(withoutWeapons)?.data\r\n if (!data) {\r\n this.store.fetchWeapons(withoutWeapons)\r\n return {}\r\n }\r\n return data\r\n },\r\n players (): { [key: string]: Player } {\r\n const { player: _, ...withoutPlayers } = this.filters\r\n const data = this.store.getPlayerList(withoutPlayers)?.data\r\n if (!data) {\r\n this.store.fetchPlayers(withoutPlayers)\r\n return {}\r\n }\r\n return data\r\n },\r\n sortedWeaponList (): string[] {\r\n if (!this.weapons) return []\r\n const weapons = Object.keys(this.weapons)\r\n return weapons.sort()\r\n },\r\n sortedServerList ():string[] {\r\n if (!this.servers) return []\r\n const servers = Object.keys(this.servers)\r\n return servers.sort()\r\n },\r\n sortedPlayerList (): string[] {\r\n if (!this.players) return []\r\n const players = Object.keys(this.players)\r\n return players.sort((a: string, b: string) => {\r\n if (!this.players) {\r\n return 0\r\n }\r\n if (this.players[a].username < this.players[b].username) {\r\n return -1\r\n }\r\n if (this.players[a].username > this.players[b].username) {\r\n return 1\r\n }\r\n return 0\r\n })\r\n }\r\n },\r\n watch: {\r\n model: {\r\n handler (newModel) {\r\n this.filters.server = newModel.server?.name\r\n this.filters.weapon = newModel.weapon\r\n },\r\n deep: true\r\n }\r\n }\r\n})\r\n","import { render } from \"./PlayerView.vue?vue&type=template&id=8bebdda4&scoped=true&ts=true\"\nimport script from \"./PlayerView.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerView.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerView.vue?vue&type=style&index=0&id=8bebdda4&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-8bebdda4\"]])\n\nexport default __exports__","import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'\r\nimport HomeView from '../views/HomeView.vue'\r\nimport PlayerView from '../views/PlayerView.vue'\r\n\r\nconst routes: Array = [\r\n {\r\n path: '/',\r\n name: 'home',\r\n component: PlayerView\r\n }\r\n // {\r\n // path: '/players',\r\n // name: 'players',\r\n // component: PlayerView\r\n // },\r\n // {\r\n // path: '/about',\r\n // name: 'about',\r\n // // route level code-splitting\r\n // // this generates a separate chunk (about.[hash].js) for this route\r\n // // which is lazy-loaded when the route is visited.\r\n // component: () => import(/* webpackChunkName: \"about\" */ '../views/AboutView.vue')\r\n // }\r\n]\r\n\r\nconst router = createRouter({\r\n history: createWebHistory(process.env.BASE_URL),\r\n routes\r\n})\r\n\r\nexport default router\r\n","import { createApp } from 'vue'\r\nimport App from './App.vue'\r\nimport router from './router'\r\nimport { createPinia } from 'pinia'\r\n\r\nconst pinia = createPinia()\r\n\r\ncreateApp(App).use(pinia).use(router).mount('#app')\r\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t143: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunktoneapi_webclient\"] = self[\"webpackChunktoneapi_webclient\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [998], function() { return __webpack_require__(3870); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["_hoisted_1","_createStaticVNode","render","_ctx","_cache","$props","$setup","$data","$options","_component_router_link","_resolveComponent","_component_router_view","_openBlock","_createElementBlock","_Fragment","_createElementVNode","_createVNode","to","class","default","_withCtx","_createTextVNode","_","removeNullEntries","a","Object","fromEntries","entries","filter","e","undefined","objectEqual","b","assert","deepStrictEqual","useKillStore","defineStore","state","servers","players","weapons","maps","gamemodes","hosts","getters","getPlayerList","filters","find","getWeaponList","getServerList","actions","async","response","fetch","URLSearchParams","data","json","entry","this","push","defineComponent","setup","props","ctx","store","fetchPlayers","fetchServers","fetchWeapons","__exports__","id","_hoisted_2","_component_VueMultiselect","_component_PlayerList","_component_PlayerChart","_component_WeaponChart","selectLabel","deselectLabel","placeholder","modelValue","model","server","$event","options","groupedServers","group_label","multiple","name","label","weapon","sortedWeaponList","playerHighlighted","sortedPlayerList","username","onHighlightPlayer","player","_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_3","onKeydown","args","selectNextPlayer","tabindex","onClick","sortPlayerList","_normalizeClass","sortingData","argument","_renderList","playerIdList","playerId","index","key","$emit","ref_for","ref","_toDisplayString","kills","deaths","Math","round","max","max_distance","total_distance","type","String","emits","direction","computed","withoutPlayer","watch","handler","newval","keys","slice","immediate","newElement","$refs","scrollIntoView","behavior","block","updated","element","methods","arg","sort","varA","varB","values","Home","Infinity","End","PageDown","PageUp","ArrowUp","ArrowDown","ArrowRight","ArrowLeft","includes","preventDefault","indexOf","nextIndex","length","_component_Scatter","chart","chartOptions","ChartJS","LinearScale","PointElement","LineElement","Tooltip","Legend","annotationPlugin","dataLabel","refreshColors","components","Scatter","mounted","colors","container","style","getComputedStyle","fg","getPropertyValue","bg","orange","cyan","currentLine","datasets","labels","borderColor","context","backgroundColor","pointRadius","pointStyle","hoverRadius","map","y","x","endX","endY","maxX","maxY","responsive","maintainAspectRatio","animation","duration","layout","autoPadding","scales","title","text","display","color","ticks","plugins","tooltip","callbacks","dataset","dataIndex","parsed","annotation","annotations","line","yMin","xMin","yMax","xMax","borderWidth","borderDash","legend","datalabels","formatter","value","borderRadius","align","anchor","clamp","onHover","native","target","cursor","cut","_component_Doughnut","ArcElement","Doughnut","yellow","green","purple","red","pink","chartData","padding","withoutWeapon","Number","VueMultiselect","PlayerList","PlayerChart","WeaponChart","_1","withoutServer","forEach","host","withoutWeapons","withoutPlayers","sortedServerList","newModel","deep","routes","path","component","PlayerView","router","createRouter","history","createWebHistory","process","pinia","createPinia","createApp","App","use","mount","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","m","deferred","O","result","chunkIds","fn","priority","notFulfilled","i","fulfilled","j","every","splice","r","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","window","obj","prop","prototype","hasOwnProperty","call","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/js/app.f8f821bc.js b/dist/js/app.f8f821bc.js deleted file mode 100644 index 7312cb4..0000000 --- a/dist/js/app.f8f821bc.js +++ /dev/null @@ -1,2 +0,0 @@ -(function(){"use strict";var e={3870:function(e,t,r){var s=r(3862),a=r(3396);const i=(0,a.uE)('
',4);function l(e,t,r,s,l,o){const n=(0,a.up)("router-link"),h=(0,a.up)("router-view");return(0,a.wg)(),(0,a.iD)(a.HY,null,[(0,a._)("header",null,[(0,a._)("nav",null,[i,(0,a.Wm)(n,{to:"/",class:"navbar-element"},{default:(0,a.w5)((()=>[(0,a.Uk)("Players")])),_:1})])]),(0,a.Wm)(h)],64)}r(7658);var o=r(1020),n=r(5130);function h(e){return Object.fromEntries(Object.entries(e).filter((e=>void 0!==e[1]&&null!==e[1])))}function p(e,t){try{return e=h(e),t=h(t),n.deepStrictEqual(e,t),!0}catch{return!1}}const d=(0,o.Q_)("kill",{state:()=>({servers:[],players:[],weapons:[],maps:[],gamemodes:[],hosts:{}}),getters:{getPlayerList:e=>t=>e.players.find((e=>p(e.filter,t))),getWeaponList:e=>t=>e.weapons.find((e=>p(e.filter,t))),getServerList:e=>t=>e.servers.find((e=>p(e.filter,t)))},actions:{async fetchPlayers(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2_test/client/players?"+new URLSearchParams(e)),r=await t.json(),s=this.players.find((t=>p(t.filter,e)));if(!s)return this.players.push({filter:e,data:r});s.data=r},async fetchWeapons(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2_test/client/weapons?"+new URLSearchParams(e)),r=await t.json(),s=this.weapons.find((t=>p(t.filter,e)));if(!s)return this.weapons.push({filter:e,data:r});s.data=r},async fetchServers(e){e=h(e);const t=await fetch("https://tone.sleepycat.date/v2_test/client/servers?"+new URLSearchParams(e)),r=await t.json(),s=this.servers.find((t=>p(t.filter,e)));if(!s)return this.servers.push({filter:e,data:r});s.data=r}}});var c=(0,a.aZ)({setup(e,t){const r=d();r.fetchPlayers({}),r.fetchServers({}),r.fetchWeapons({})}}),u=r(89);const g=(0,u.Z)(c,[["render",l]]);var y=g,f=r(2483);const m={id:"filters"},v={id:"playerView"};function b(e,t,r,s,i,l){const o=(0,a.up)("VueMultiselect"),n=(0,a.up)("PlayerList"),h=(0,a.up)("PlayerChart"),p=(0,a.up)("WeaponChart");return(0,a.wg)(),(0,a.iD)(a.HY,null,[(0,a._)("div",m,[(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Select server",modelValue:e.model.server,"onUpdate:modelValue":t[0]||(t[0]=t=>e.model.server=t),options:e.groupedServers,"group-values":"servers",group_label:"id","group-select":!1,"allow-empty":!0,multiple:!1,"custom-label":e=>e.name,"track-by":"name",label:"name"},null,8,["modelValue","options","custom-label"]),(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Select weapon",modelValue:e.model.weapon,"onUpdate:modelValue":t[1]||(t[1]=t=>e.model.weapon=t),options:e.sortedWeaponList,"allow-empty":!0},null,8,["modelValue","options"]),(0,a.Wm)(o,{selectLabel:"",deselectLabel:"remove",placeholder:"Search player",modelValue:e.playerHighlighted,"onUpdate:modelValue":t[2]||(t[2]=t=>e.playerHighlighted=t),options:e.sortedPlayerList,"allow-empty":!0,"custom-label":t=>e.players[t]?.username},null,8,["modelValue","options","custom-label"])]),(0,a._)("div",v,[(0,a.Wm)(n,{filters:e.filters,onHighlightPlayer:t[3]||(t[3]=t=>e.playerHighlighted=t),playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"]),(0,a.Wm)(h,{filters:e.filters,onHighlightPlayer:t[4]||(t[4]=t=>e.playerHighlighted=t),playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"]),(0,a.Wm)(p,{filters:{player:e.playerHighlighted,...e.filters},playerHighlighted:e.playerHighlighted},null,8,["filters","playerHighlighted"])])],64)}var w=r(7139);const k=e=>((0,a.dD)("data-v-33cdd346"),e=e(),(0,a.Cn)(),e),L={class:"playerHeaders"},P=k((()=>(0,a._)("span",null,null,-1))),_=["onClick"];function H(e,t,r,s,i,l){return(0,a.wg)(),(0,a.iD)("div",{class:"playerTable",onKeydown:t[6]||(t[6]=(...t)=>e.selectNextPlayer&&e.selectNextPlayer(...t)),tabindex:"0"},[(0,a._)("div",L,[P,(0,a._)("span",{onClick:t[0]||(t[0]=t=>e.sortPlayerList("username")),class:(0,w.C_)("username"==e.sortingData.argument?"selected":"")},"Username",2),(0,a._)("span",{onClick:t[1]||(t[1]=t=>e.sortPlayerList("kills")),class:(0,w.C_)("kills"==e.sortingData.argument?"selected":"")},"K",2),(0,a._)("span",{onClick:t[2]||(t[2]=t=>e.sortPlayerList("deaths")),class:(0,w.C_)("deaths"==e.sortingData.argument?"selected":"")},"D",2),(0,a._)("span",{onClick:t[3]||(t[3]=t=>e.sortPlayerList("k/d")),class:(0,w.C_)("k/d"==e.sortingData.argument?"selected":"")},"K/D",2),(0,a._)("span",{onClick:t[4]||(t[4]=t=>e.sortPlayerList("max_distance")),class:(0,w.C_)("max_distance"==e.sortingData.argument?"selected":"")},"max distance",2),(0,a._)("span",{onClick:t[5]||(t[5]=t=>e.sortPlayerList("avg_distance")),class:(0,w.C_)("avg_distance"==e.sortingData.argument?"selected":"")},"average distance",2)]),((0,a.wg)(!0),(0,a.iD)(a.HY,null,(0,a.Ko)(e.playerIdList,((t,r)=>((0,a.wg)(),(0,a.iD)("div",{class:(0,w.C_)("playerRow "+(t===e.$props.playerHighlighted?"selected":"")),key:t,onClick:r=>e.$emit("highlightPlayer",t),ref_for:!0,ref:"player:"+t},[(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(r+1),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].username),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].kills),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].deaths),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(Math.round(e.players[t].kills/Math.max(1,e.players[t].deaths)*100)/100),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(e.players[t].max_distance),1)]),(0,a._)("div",null,[(0,a._)("span",null,(0,w.zw)(Math.round(100*(e.players[t].total_distance/e.players[t].kills||0))/100),1)])],10,_)))),128))],32)}var I=(0,a.aZ)({props:{filters:{type:Object,default:()=>({})},playerHighlighted:String},emits:["highlightPlayer"],data(){return{sortingData:{direction:-1,argument:"kills"},playerIdList:[],store:d()}},computed:{players(){const{player:e,...t}=this.filters;return this.store.getPlayerList(t)?.data||{}}},watch:{players:{handler(e){e&&(this.playerIdList=[],this.sortingData.direction*=-1,this.playerIdList=Object.keys(e),this.sortPlayerList(this.sortingData.argument),this.playerIdList=this.playerIdList.slice(0,500))},immediate:!0},playerHighlighted(e){const t=this.$refs["player:"+e];t&&t[0]&&t[0].scrollIntoView({behavior:"smooth",block:"center"})}},updated(){const e=this.$refs["player:"+this.$props.playerHighlighted];e&&e[0]&&e[0].scrollIntoView({behavior:"smooth",block:"center"})},methods:{sortPlayerList(e){e===this.sortingData.argument?this.sortingData.direction*=-1:"username"===e&&(this.sortingData.direction=1),this.sortingData.argument=e,this.playerIdList.sort(((t,r)=>{if(!this.players)return 0;let s,a;return"k/d"===e?(s=this.players[t].kills/Math.max(1,this.players[t].deaths),a=this.players[r].kills/Math.max(1,this.players[r].deaths)):"avg_distance"===e?(s=this.players[t].total_distance/this.players[t].kills||0,a=this.players[r].total_distance/this.players[r].kills||0):(s=this.players[t][e],a=this.players[r][e]),void 0===s||void 0===a?0:sa?1*this.sortingData.direction:0}))},selectNextPlayer(e){const t={Home:-1/0,End:1/0,PageDown:100,PageUp:-100,ArrowUp:-1,ArrowDown:1,ArrowRight:10,ArrowLeft:-10};if(!this.$props.playerHighlighted)return;if(!Object.keys(t).includes(e.key))return;e.preventDefault();const r=this.playerIdList.indexOf(this.$props.playerHighlighted);let s=r+t[e.key];s>=this.playerIdList.length&&(s=this.playerIdList.length-1),s<0&&(s=0),this.$emit("highlightPlayer",this.playerIdList[s])}}});const C=(0,u.Z)(I,[["render",H],["__scopeId","data-v-33cdd346"]]);var x=C;const O={class:"playerChart",ref:"container"};function $(e,t,r,s,i,l){const o=(0,a.up)("Scatter");return(0,a.wg)(),(0,a.iD)("div",O,[(0,a.Wm)(o,{data:e.chart,options:e.chartOptions},null,8,["data","options"])],512)}var D=r(3254),W=r(9152),V=r(1131),j=r(5866);D.kL.register(D.f$,D.od,D.jn,D.u,D.De,W.Z,V.Z);var S=(0,a.aZ)({name:"PlayerChart",props:{filters:Object,playerHighlighted:String},data:()=>({store:d(),refreshColors:0}),emits:["highlightPlayer"],components:{Scatter:j.bp},mounted(){this.refreshColors++},computed:{colors(){this.refreshColors;const e={};if(this.$refs.container){const t=getComputedStyle(this.$refs.container);e.fg=t.getPropertyValue("--foreground"),e.bg=t.getPropertyValue("--bg-color"),e.orange=t.getPropertyValue("--orange"),e.cyan=t.getPropertyValue("--cyan"),e.currentLine=t.getPropertyValue("--current-line")}else e.fg="#ffffff";return e},chart(){return{datasets:[{label:"Players",labels:this.playerIdList||[],borderColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?this.colors.orange:this.colors.cyan,backgroundColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?this.colors.orange:this.colors.cyan,pointRadius:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?20:1,pointStyle:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?"crossRot":"circle",hoverRadius:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.index]?30:4,data:this.playerIdList.map((e=>({y:this.players[e].kills,x:this.players[e].deaths})))}]}},chartOptions(){this.$props.playerHighlighted;let e=0,t=0;if(this.players){const r=Math.max(...Object.values(this.players).map((e=>e.deaths))),s=Math.max(...Object.values(this.players).map((e=>e.kills)));s>r?(e=r,t=r/s*s):(t=s,e=s/r*r)}return{responsive:!0,maintainAspectRatio:!1,animation:{duration:500},layout:{autoPadding:!1},scales:{y:{title:{text:"Kills",display:!0,color:this.colors.fg},ticks:{color:this.colors.fg}},x:{title:{text:"Deaths",display:!0,color:this.colors.fg},ticks:{color:this.colors.fg}}},plugins:{tooltip:{callbacks:{label:e=>{let t;return t=this.players?this.players[e.dataset.labels[e.dataIndex]].username:e.dataset.labels[e.dataIndex],t+=" ("+e.parsed.y+" kills "+e.parsed.x+" deaths)",t}}},annotation:{annotations:{line:{type:"line",yMin:0,xMin:0,yMax:t,xMax:e,borderWidth:2,borderColor:this.colors.orange,borderDash:[1,5]}}},legend:{display:!1},datalabels:{formatter:(e,t)=>this.players[this.playerIdList[t.dataIndex]].username,backgroundColor:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?this.colors.orange:null,borderColor:this.colors.fg,borderWidth:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?1:0,borderRadius:5,display:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?"true":"auto",align:-45,anchor:"end",clamp:!0,color:e=>this.$props.playerHighlighted&&this.$props.playerHighlighted===this.playerIdList[e.dataIndex]?this.colors.bg:this.colors.fg}},onClick:(e,t)=>{this.$emit("highlightPlayer",t.length>0?this.playerIdList[t[0].index]:void 0)},onHover:(e,t)=>{e.native.target&&(e.native.target.style.cursor=t[0]?"pointer":"default")}}},players(){const e=this.store.getPlayerList(this.filters||{})?.data;if(!e)return{};const t=Object.entries(e).sort(((e,t)=>e[1].killst[1].kills?-1:0)).slice(0,200);return Object.fromEntries(t)},playerIdList(){return Object.keys(this.players)}}});const M=(0,u.Z)(S,[["render",$],["__scopeId","data-v-a55781c4"]]);var Z=M;const R={class:"weaponChart",ref:"container"};function U(e,t,r,s,i,l){const o=(0,a.up)("Doughnut");return(0,a.wg)(),(0,a.iD)("div",R,[(0,a.Wm)(o,{data:e.chart,options:e.chartOptions},null,8,["data","options"])],512)}D.kL.register(D.qi,D.u,D.De,V.Z);var z=(0,a.aZ)({name:"PlayerChart",props:{filters:Object,playerHighlighted:String},emits:["highlightPlayer"],components:{Doughnut:j.$I},mounted(){this.refreshColors++},data:()=>({store:d(),refreshColors:0}),computed:{colors(){this.refreshColors;const e={};if(this.$refs.container){const t=getComputedStyle(this.$refs.container);e.fg=t.getPropertyValue("--foreground"),e.bg=t.getPropertyValue("--bg-color"),e.orange=t.getPropertyValue("--orange"),e.cyan=t.getPropertyValue("--cyan"),e.yellow=t.getPropertyValue("--yellow"),e.green=t.getPropertyValue("--green"),e.purple=t.getPropertyValue("--purple"),e.red=t.getPropertyValue("--red"),e.pink=t.getPropertyValue("--pink"),e.currentLine=t.getPropertyValue("--current-line")}else e.fg="#ffffff";return e},chart(){const e=["cyan","green","orange","pink","purple","red","yellow"],t={datasets:[{label:"Weapons",labels:this.sortedWeaponList||[],borderColor:()=>this.colors.fg,backgroundColor:t=>this.colors[e[3*t.dataIndex%e.length]],data:[]}]};return this.sortedWeaponList?(t.datasets[0].data=this.sortedWeaponList.map((e=>this.weapons?this.weapons[e].kills:0)),t):t},chartOptions(){this.$props.playerHighlighted;const e={responsive:!0,maintainAspectRatio:!0,animation:{duration:500},layout:{autoPadding:!1},plugins:{datalabels:{formatter:(e,t)=>this.sortedWeaponList[t.dataIndex],backgroundColor:e=>e.dataset.backgroundColor(e),borderColor:this.colors.fg,borderRadius:25,borderWidth:2,color:this.colors.bg,display:e=>e.dataIndex===e.dataset.labels.length-1||"auto",padding:6},tooltip:{callbacks:{label:e=>{let t;return t=this.sortedWeaponList?this.sortedWeaponList[e.dataIndex]:e.dataset.labels[e.dataIndex],t+=" ("+this.weapons[t].kills+" kills)",t}}}}};return e},weapons(){const{weapon:e,...t}=this.filters||{},r=this.store.getWeaponList(t)?.data;return r||(this.store.fetchWeapons(t),{})},sortedWeaponList(){if(!this.weapons)return[];const e=Object.keys(this.weapons);return e.sort(((e,t)=>Number(this.weapons[e].kills)Number(this.weapons[t].kills)?1:0)),e}}});const A=(0,u.Z)(z,[["render",U],["__scopeId","data-v-673fd0b6"]]);var N=A,E=r(6368),T=(0,a.aZ)({name:"PlayerView",components:{VueMultiselect:E.ZP,PlayerList:x,PlayerChart:Z,WeaponChart:N},data(){return{model:{server:void 0,weapon:void 0},filters:{},store:d(),playerHighlighted:void 0}},computed:{servers(){const{server:e,player:t,...r}=this.filters,s=this.store.getServerList(r)?.data;return s||(this.store.fetchServers(r),{})},groupedServers(){const e=[];return Object.entries(this.servers).forEach((t=>{e.find((e=>e.id===t[1].host+"sfdsdfsd"))||e.push({id:t[1].host+"sfdsdfsd",servers:[]}),e.find((e=>e.id===t[1].host+"sfdsdfsd"))?.servers.push({name:t[0],...t[1]})})),e},weapons(){const{weapon:e,player:t,...r}=this.filters,s=this.store.getWeaponList(r)?.data;return s||(this.store.fetchWeapons(r),{})},players(){const{player:e,...t}=this.filters,r=this.store.getPlayerList(t)?.data;return r||(this.store.fetchPlayers(t),{})},sortedWeaponList(){if(!this.weapons)return[];const e=Object.keys(this.weapons);return e.sort()},sortedServerList(){if(!this.servers)return[];const e=Object.keys(this.servers);return e.sort()},sortedPlayerList(){if(!this.players)return[];const e=Object.keys(this.players);return e.sort(((e,t)=>this.players?this.players[e].usernamethis.players[t].username?1:0:0))}},watch:{model:{handler(e){this.filters.server=e.server?.name,this.filters.weapon=e.weapon},deep:!0}}});const K=(0,u.Z)(T,[["render",b],["__scopeId","data-v-8bebdda4"]]);var Y=K;const q=[{path:"/",name:"home",component:Y}],B=(0,f.p7)({history:(0,f.PO)("/ToneAPI_webclient/"),routes:q});var F=B;const G=(0,o.WB)();(0,s.ri)(y).use(G).use(F).mount("#app")}},t={};function r(s){var a=t[s];if(void 0!==a)return a.exports;var i=t[s]={exports:{}};return e[s](i,i.exports,r),i.exports}r.m=e,function(){var e=[];r.O=function(t,s,a,i){if(!s){var l=1/0;for(p=0;p=i)&&Object.keys(r.O).every((function(e){return r.O[e](s[n])}))?s.splice(n--,1):(o=!1,i0&&e[p-1][2]>i;p--)e[p]=e[p-1];e[p]=[s,a,i]}}(),function(){r.n=function(e){var t=e&&e.__esModule?function(){return e["default"]}:function(){return e};return r.d(t,{a:t}),t}}(),function(){r.d=function(e,t){for(var s in t)r.o(t,s)&&!r.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})}}(),function(){r.g=function(){if("object"===typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"===typeof window)return window}}()}(),function(){r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)}}(),function(){var e={143:0};r.O.j=function(t){return 0===e[t]};var t=function(t,s){var a,i,l=s[0],o=s[1],n=s[2],h=0;if(l.some((function(t){return 0!==e[t]}))){for(a in o)r.o(o,a)&&(r.m[a]=o[a]);if(n)var p=n(r)}for(t&&t(s);hTONE API
\", 4)\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_router_link = _resolveComponent(\"router-link\")!\n const _component_router_view = _resolveComponent(\"router-view\")!\n\n return (_openBlock(), _createElementBlock(_Fragment, null, [\n _createElementVNode(\"header\", null, [\n _createElementVNode(\"nav\", null, [\n _hoisted_1,\n _createVNode(_component_router_link, {\n to: \"/\",\n class: \"navbar-element\"\n }, {\n default: _withCtx(() => [\n _createTextVNode(\"Players\")\n ]),\n _: 1\n })\n ])\n ]),\n _createVNode(_component_router_view)\n ], 64))\n}","import { defineStore } from 'pinia'\r\nimport * as assert from 'assert'\r\n\r\nfunction removeNullEntries (a:any) {\r\n return Object.fromEntries(Object.entries(a).filter(e => e[1] !== undefined && e[1] !== null))\r\n}\r\nfunction objectEqual (a:any, b:any) {\r\n try {\r\n a = removeNullEntries(a)\r\n b = removeNullEntries(b)\r\n assert.deepStrictEqual(a, b)\r\n return true\r\n } catch {\r\n return false\r\n }\r\n}\r\nexport interface Filters {\r\n server?: string;\r\n player?: string;\r\n weapon?: string;\r\n host?: string;\r\n map?: string;\r\n gamemode?: string;\r\n}\r\n\r\nexport interface Kill {\r\n deaths: number;\r\n kills: number;\r\n // eslint-disable-next-line camelcase\r\n max_distance: number;\r\n // eslint-disable-next-line camelcase\r\n total_distance: number;\r\n}\r\nexport interface KillData {\r\n filter: Filters;\r\n data: { [key: string]: T };\r\n}\r\n\r\nexport interface Player extends Kill {\r\n username: string;\r\n // eslint-disable-next-line camelcase\r\n deaths_while_equipped?: number;\r\n}\r\n\r\nexport interface Weapon extends Kill {\r\n // eslint-disable-next-line camelcase\r\n deaths_while_equipped: number;\r\n}\r\n\r\nexport interface Server extends Kill {\r\n host: number;\r\n}\r\n\r\n// define your typings for the store state\r\nexport interface State {\r\n servers: KillData[];\r\n players: KillData[];\r\n weapons: KillData[];\r\n maps: KillData[];\r\n gamemodes: KillData[];\r\n hosts: { [key: number]: string };\r\n}\r\n\r\nexport const useKillStore = defineStore('kill', {\r\n state: (): State => ({\r\n servers: [],\r\n players: [],\r\n weapons: [],\r\n maps: [],\r\n gamemodes: [],\r\n hosts: {}\r\n }),\r\n getters: {\r\n getPlayerList: (state) => (filters: Filters) => state.players.find((e) => objectEqual(e.filter, filters)),\r\n getWeaponList: (state) => (filters: Filters) => state.weapons.find((e) => objectEqual(e.filter, filters)),\r\n getServerList: (state) => (filters: Filters) => state.servers.find((e) => objectEqual(e.filter, filters))\r\n },\r\n actions: {\r\n async fetchPlayers (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2_test/client/players?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.players.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.players.push({ filter, data })\r\n entry.data = data\r\n },\r\n async fetchWeapons (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2_test/client/weapons?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.weapons.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.weapons.push({ filter, data })\r\n entry.data = data\r\n },\r\n async fetchServers (filter: Filters) {\r\n filter = removeNullEntries(filter)\r\n const response = await fetch(\r\n 'https://tone.sleepycat.date/v2_test/client/servers?' +\r\n new URLSearchParams(filter as Record)\r\n )\r\n const data = await response.json()\r\n const entry = this.servers.find((e) => objectEqual(e.filter, filter))\r\n if (!entry) return this.servers.push({ filter, data })\r\n entry.data = data\r\n }\r\n }\r\n})\r\n","\r\nimport { Player, Weapon, Server, useKillStore } from '@/stores/kill'\r\nimport { defineComponent } from 'vue'\r\n\r\nexport default defineComponent({\r\n setup (props, ctx) {\r\n const store = useKillStore()\r\n store.fetchPlayers({})\r\n store.fetchServers({})\r\n store.fetchWeapons({})\r\n }\r\n})\r\n","import { render } from \"./App.vue?vue&type=template&id=a4a5fcd4&ts=true\"\nimport script from \"./App.vue?vue&type=script&lang=ts\"\nexport * from \"./App.vue?vue&type=script&lang=ts\"\n\nimport \"./App.vue?vue&type=style&index=0&id=a4a5fcd4&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, createElementVNode as _createElementVNode, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-8bebdda4\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = { id: \"filters\" }\nconst _hoisted_2 = { id: \"playerView\" }\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_VueMultiselect = _resolveComponent(\"VueMultiselect\")!\n const _component_PlayerList = _resolveComponent(\"PlayerList\")!\n const _component_PlayerChart = _resolveComponent(\"PlayerChart\")!\n const _component_WeaponChart = _resolveComponent(\"WeaponChart\")!\n\n return (_openBlock(), _createElementBlock(_Fragment, null, [\n _createElementVNode(\"div\", _hoisted_1, [\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Select server\",\n modelValue: _ctx.model.server,\n \"onUpdate:modelValue\": _cache[0] || (_cache[0] = ($event: any) => ((_ctx.model.server) = $event)),\n options: _ctx.groupedServers,\n \"group-values\": \"servers\",\n group_label: \"id\",\n \"group-select\": false,\n \"allow-empty\": true,\n multiple: false,\n \"custom-label\": ((e) => e.name),\n \"track-by\": \"name\",\n label: \"name\"\n }, null, 8, [\"modelValue\", \"options\", \"custom-label\"]),\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Select weapon\",\n modelValue: _ctx.model.weapon,\n \"onUpdate:modelValue\": _cache[1] || (_cache[1] = ($event: any) => ((_ctx.model.weapon) = $event)),\n options: _ctx.sortedWeaponList,\n \"allow-empty\": true\n }, null, 8, [\"modelValue\", \"options\"]),\n _createVNode(_component_VueMultiselect, {\n selectLabel: \"\",\n deselectLabel: \"remove\",\n placeholder: \"Search player\",\n modelValue: _ctx.playerHighlighted,\n \"onUpdate:modelValue\": _cache[2] || (_cache[2] = ($event: any) => ((_ctx.playerHighlighted) = $event)),\n options: _ctx.sortedPlayerList,\n \"allow-empty\": true,\n \"custom-label\": ((e) => _ctx.players[e]?.username)\n }, null, 8, [\"modelValue\", \"options\", \"custom-label\"])\n ]),\n _createElementVNode(\"div\", _hoisted_2, [\n _createVNode(_component_PlayerList, {\n filters: _ctx.filters,\n onHighlightPlayer: _cache[3] || (_cache[3] = ($event: any) => (_ctx.playerHighlighted = $event)),\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"]),\n _createVNode(_component_PlayerChart, {\n filters: _ctx.filters,\n onHighlightPlayer: _cache[4] || (_cache[4] = ($event: any) => (_ctx.playerHighlighted = $event)),\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"]),\n _createVNode(_component_WeaponChart, {\n filters: {player: _ctx.playerHighlighted, ..._ctx.filters},\n playerHighlighted: _ctx.playerHighlighted\n }, null, 8, [\"filters\", \"playerHighlighted\"])\n ])\n ], 64))\n}","import { createElementVNode as _createElementVNode, normalizeClass as _normalizeClass, renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, toDisplayString as _toDisplayString, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-33cdd346\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = { class: \"playerHeaders\" }\nconst _hoisted_2 = /*#__PURE__*/ _withScopeId(() => /*#__PURE__*/_createElementVNode(\"span\", null, null, -1))\nconst _hoisted_3 = [\"onClick\"]\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n return (_openBlock(), _createElementBlock(\"div\", {\n class: \"playerTable\",\n onKeydown: _cache[6] || (_cache[6] = \n//@ts-ignore\n(...args) => (_ctx.selectNextPlayer && _ctx.selectNextPlayer(...args))),\n tabindex: \"0\"\n }, [\n _createElementVNode(\"div\", _hoisted_1, [\n _hoisted_2,\n _createElementVNode(\"span\", {\n onClick: _cache[0] || (_cache[0] = ($event: any) => (_ctx.sortPlayerList('username'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'username' ? 'selected' : '')\n }, \"Username\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[1] || (_cache[1] = ($event: any) => (_ctx.sortPlayerList('kills'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'kills' ? 'selected' : '')\n }, \"K\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[2] || (_cache[2] = ($event: any) => (_ctx.sortPlayerList('deaths'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'deaths' ? 'selected' : '')\n }, \"D\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[3] || (_cache[3] = ($event: any) => (_ctx.sortPlayerList('k/d'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'k/d' ? 'selected' : '')\n }, \"K/D\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[4] || (_cache[4] = ($event: any) => (_ctx.sortPlayerList('max_distance'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'max_distance' ? 'selected' : '')\n }, \"max distance\", 2),\n _createElementVNode(\"span\", {\n onClick: _cache[5] || (_cache[5] = ($event: any) => (_ctx.sortPlayerList('avg_distance'))),\n class: _normalizeClass(_ctx.sortingData.argument == 'avg_distance' ? 'selected' : '')\n }, \"average distance\", 2)\n ]),\n (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_ctx.playerIdList, (playerId, index) => {\n return (_openBlock(), _createElementBlock(\"div\", {\n class: _normalizeClass('playerRow ' + (playerId === _ctx.$props.playerHighlighted ? 'selected' : '')),\n key: playerId,\n onClick: ($event: any) => (_ctx.$emit('highlightPlayer', playerId)),\n ref_for: true,\n ref: `player:` + playerId\n }, [\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(index+1), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].username), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].kills), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].deaths), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(Math.round(_ctx.players[playerId].kills / Math.max(1, _ctx.players[playerId].deaths) * 100) / 100), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(_ctx.players[playerId].max_distance), 1)\n ]),\n _createElementVNode(\"div\", null, [\n _createElementVNode(\"span\", null, _toDisplayString(Math.round(((_ctx.players[playerId].total_distance / _ctx.players[playerId].kills) || 0) * 100) / 100), 1)\n ])\n ], 10, _hoisted_3))\n }), 128))\n ], 32))\n}","\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { useKillStore, Player, Filters } from '@/stores/kill'\r\n\r\nexport default defineComponent({\r\n props: {\r\n filters: { type: Object as PropType, default: () => ({}) },\r\n playerHighlighted: String\r\n },\r\n emits: ['highlightPlayer'],\r\n data () {\r\n return {\r\n sortingData: { direction: -1, argument: 'kills' as keyof Player | 'k/d' | 'avg_distance' },\r\n playerIdList: [] as string[],\r\n store: useKillStore()\r\n }\r\n },\r\n computed: {\r\n players (): { [key: string]: Player } {\r\n const { player: _, ...withoutPlayer } = this.filters\r\n return this.store.getPlayerList(withoutPlayer)?.data || {}\r\n }\r\n },\r\n watch: {\r\n players: {\r\n handler (newval: { [key: string]: Player }): void {\r\n if (!newval) return\r\n this.playerIdList = []\r\n this.sortingData.direction *= -1\r\n this.playerIdList = Object.keys(newval)\r\n this.sortPlayerList(this.sortingData.argument)\r\n this.playerIdList = this.playerIdList.slice(0, 500)\r\n },\r\n immediate: true\r\n },\r\n playerHighlighted (newval) {\r\n const newElement = this.$refs['player:' + newval] as HTMLElement[]\r\n if (newElement && newElement[0]) { newElement[0].scrollIntoView({ behavior: 'smooth', block: 'center' }) }\r\n }\r\n },\r\n updated () {\r\n const element = this.$refs['player:' + this.$props.playerHighlighted] as HTMLElement[]\r\n if (!element || !element[0]) return\r\n element[0].scrollIntoView({ behavior: 'smooth', block: 'center' })\r\n },\r\n methods: {\r\n sortPlayerList (arg: ((keyof Player) | 'k/d' | 'avg_distance')) {\r\n if (arg === this.sortingData.argument) {\r\n this.sortingData.direction *= -1\r\n } else {\r\n if (arg === 'username') {\r\n this.sortingData.direction = 1\r\n }\r\n }\r\n this.sortingData.argument = arg\r\n\r\n this.playerIdList.sort((a: string, b: string) => {\r\n if (!this.players) {\r\n return 0\r\n }\r\n let varA, varB\r\n if (arg === 'k/d') {\r\n varA = this.players[a].kills / Math.max(1, this.players[a].deaths)\r\n varB = this.players[b].kills / Math.max(1, this.players[b].deaths)\r\n } else if (arg === 'avg_distance') {\r\n varA = (this.players[a].total_distance / this.players[a].kills) || 0\r\n varB = (this.players[b].total_distance / this.players[b].kills) || 0\r\n } else {\r\n varA = this.players[a][arg]\r\n varB = this.players[b][arg]\r\n }\r\n if (varA === undefined || varB === undefined) return 0\r\n if (varA < varB) {\r\n return -1 * this.sortingData.direction\r\n }\r\n if (varA > varB) {\r\n return 1 * this.sortingData.direction\r\n }\r\n return 0\r\n })\r\n },\r\n selectNextPlayer (e: KeyboardEvent) {\r\n const values = {\r\n Home: -Infinity,\r\n End: Infinity,\r\n PageDown: 100,\r\n PageUp: -100,\r\n ArrowUp: -1,\r\n ArrowDown: 1,\r\n ArrowRight: 10,\r\n ArrowLeft: -10\r\n } as { [key: string]: number }\r\n if (!this.$props.playerHighlighted) return\r\n if (!Object.keys(values).includes(e.key)) return\r\n e.preventDefault()\r\n const index = this.playerIdList.indexOf(this.$props.playerHighlighted)\r\n let nextIndex = (index + values[e.key])\r\n if (nextIndex >= this.playerIdList.length) nextIndex = this.playerIdList.length - 1\r\n if (nextIndex < 0) nextIndex = 0\r\n this.$emit('highlightPlayer', this.playerIdList[nextIndex])\r\n }\r\n }\r\n\r\n})\r\n","import { render } from \"./PlayerList.vue?vue&type=template&id=33cdd346&scoped=true&ts=true\"\nimport script from \"./PlayerList.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerList.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerList.vue?vue&type=style&index=0&id=33cdd346&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-33cdd346\"]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-a55781c4\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n class: \"playerChart\",\n ref: \"container\"\n}\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_Scatter = _resolveComponent(\"Scatter\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n _createVNode(_component_Scatter, {\n data: _ctx.chart,\n options: _ctx.chartOptions\n }, null, 8, [\"data\", \"options\"])\n ], 512))\n}","\r\nimport {\r\n Chart as ChartJS,\r\n LinearScale,\r\n PointElement,\r\n LineElement,\r\n Tooltip,\r\n Legend,\r\n CoreChartOptions,\r\n PluginChartOptions,\r\n ScaleChartOptions\r\n} from 'chart.js'\r\nimport annotationPlugin from 'chartjs-plugin-annotation'\r\nimport dataLabel from 'chartjs-plugin-datalabels'\r\nimport { useKillStore, Player, Filters } from '@/stores/kill'\r\n\r\nimport { Scatter } from 'vue-chartjs'\r\nimport { defineComponent, PropType } from 'vue'\r\nimport { ChartEvent } from 'chart.js/dist/core/core.plugins'\r\nimport { _DeepPartialObject } from 'chart.js/dist/types/utils'\r\n\r\nChartJS.register(LinearScale, PointElement, LineElement, Tooltip, Legend, annotationPlugin, dataLabel)\r\n\r\nexport default defineComponent({\r\n name: 'PlayerChart',\r\n props: {\r\n filters: Object as PropType,\r\n playerHighlighted: String\r\n },\r\n data: () => {\r\n return {\r\n store: useKillStore(),\r\n refreshColors: 0\r\n }\r\n },\r\n emits: ['highlightPlayer'],\r\n components: {\r\n Scatter\r\n },\r\n mounted () {\r\n this.refreshColors++\r\n },\r\n computed: {\r\n colors () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.refreshColors\r\n const colors = {} as { [key: string]: string }\r\n if (this.$refs.container) {\r\n const style = getComputedStyle(this.$refs.container as Element)\r\n colors.fg = style.getPropertyValue('--foreground')\r\n colors.bg = style.getPropertyValue('--bg-color')\r\n colors.orange = style.getPropertyValue('--orange')\r\n colors.cyan = style.getPropertyValue('--cyan')\r\n colors.currentLine = style.getPropertyValue('--current-line')\r\n } else {\r\n colors.fg = '#ffffff'\r\n }\r\n return colors\r\n },\r\n chart () {\r\n return {\r\n datasets: [\r\n {\r\n label: 'Players',\r\n labels: this.playerIdList || [] as string[],\r\n borderColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? this.colors.orange : this.colors.cyan,\r\n backgroundColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? this.colors.orange : this.colors.cyan,\r\n pointRadius: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 20 : 1,\r\n pointStyle: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 'crossRot' : 'circle',\r\n hoverRadius: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.index]) ? 30 : 4,\r\n data: this.playerIdList.map((id) => ({ y: this.players[id].kills, x: this.players[id].deaths }))\r\n }\r\n ]\r\n }\r\n },\r\n chartOptions (): _DeepPartialObject & PluginChartOptions<'scatter'> & ScaleChartOptions<'scatter'>> {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.$props.playerHighlighted\r\n let endX = 0\r\n let endY = 0\r\n if (this.players) {\r\n const maxX = Math.max(...Object.values(this.players).map(e => e.deaths))\r\n const maxY = Math.max(...Object.values(this.players).map(e => e.kills))\r\n\r\n if (maxY > maxX) {\r\n endX = maxX\r\n endY = (maxX / maxY) * maxY\r\n } else {\r\n endY = maxY\r\n endX = (maxY / maxX) * maxX\r\n }\r\n }\r\n return {\r\n responsive: true,\r\n maintainAspectRatio: false,\r\n animation: { duration: 500 },\r\n layout: { autoPadding: false },\r\n scales: {\r\n y: {\r\n title: {\r\n text: 'Kills',\r\n display: true,\r\n color: this.colors.fg\r\n },\r\n ticks: {\r\n color: this.colors.fg\r\n }\r\n },\r\n x: {\r\n title: {\r\n text: 'Deaths',\r\n display: true,\r\n color: this.colors.fg\r\n },\r\n ticks: {\r\n color: this.colors.fg\r\n }\r\n }\r\n },\r\n plugins: {\r\n tooltip: {\r\n callbacks: {\r\n label: (ctx: any) => {\r\n let label: string\r\n if (!this.players) {\r\n label = ctx.dataset.labels[ctx.dataIndex]\r\n } else {\r\n label = this.players[ctx.dataset.labels[ctx.dataIndex]].username\r\n }\r\n label += ' (' + ctx.parsed.y + ' kills ' + ctx.parsed.x + ' deaths)'\r\n return label\r\n }\r\n }\r\n },\r\n annotation: {\r\n annotations: {\r\n line: {\r\n type: 'line',\r\n yMin: 0,\r\n xMin: 0,\r\n yMax: endY,\r\n xMax: endX,\r\n borderWidth: 2,\r\n borderColor: this.colors.orange,\r\n borderDash: [1, 5]\r\n }\r\n }\r\n },\r\n legend: { display: false },\r\n datalabels: {\r\n formatter: (value: any, context: any) => {\r\n return this.players[this.playerIdList[context.dataIndex]].username\r\n },\r\n backgroundColor: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? this.colors.orange : null,\r\n borderColor: this.colors.fg,\r\n borderWidth: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? 1 : 0,\r\n borderRadius: 5,\r\n display: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? 'true' : 'auto',\r\n align: -45,\r\n anchor: 'end',\r\n clamp: true,\r\n color: (context: any) => (this.$props.playerHighlighted && this.$props.playerHighlighted === this.playerIdList[context.dataIndex]) ? this.colors.bg : this.colors.fg\r\n }\r\n },\r\n onClick: (e: ChartEvent, element: any) => {\r\n this.$emit('highlightPlayer', element.length > 0 ? this.playerIdList[element[0].index] : undefined)\r\n },\r\n onHover: (e: any, element: any) => {\r\n if (!e.native.target) return\r\n (e.native.target as HTMLElement).style.cursor = element[0] ? 'pointer' : 'default'\r\n }\r\n }\r\n },\r\n players (): { [key: string]: Player } {\r\n const data = this.store.getPlayerList(this.filters || {})?.data\r\n if (!data) return {}\r\n const cut = Object.entries(data).sort((a, b) => {\r\n if (a[1].kills < b[1].kills) {\r\n return 1\r\n }\r\n if (a[1].kills > b[1].kills) {\r\n return -1\r\n }\r\n return 0\r\n }).slice(0, 200)\r\n return Object.fromEntries(cut)\r\n },\r\n playerIdList (): string[] { return Object.keys(this.players) }\r\n\r\n }\r\n})\r\n","import { render } from \"./PlayerChart.vue?vue&type=template&id=a55781c4&scoped=true&ts=true\"\nimport script from \"./PlayerChart.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerChart.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerChart.vue?vue&type=style&index=0&id=a55781c4&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-a55781c4\"]])\n\nexport default __exports__","import { resolveComponent as _resolveComponent, createVNode as _createVNode, openBlock as _openBlock, createElementBlock as _createElementBlock, pushScopeId as _pushScopeId, popScopeId as _popScopeId } from \"vue\"\n\nconst _withScopeId = n => (_pushScopeId(\"data-v-673fd0b6\"),n=n(),_popScopeId(),n)\nconst _hoisted_1 = {\n class: \"weaponChart\",\n ref: \"container\"\n}\n\nexport function render(_ctx: any,_cache: any,$props: any,$setup: any,$data: any,$options: any) {\n const _component_Doughnut = _resolveComponent(\"Doughnut\")!\n\n return (_openBlock(), _createElementBlock(\"div\", _hoisted_1, [\n _createVNode(_component_Doughnut, {\n data: _ctx.chart,\n options: _ctx.chartOptions\n }, null, 8, [\"data\", \"options\"])\n ], 512))\n}","\r\nimport { Chart as ChartJS, ArcElement, Tooltip, Legend } from 'chart.js'\r\nimport dataLabel from 'chartjs-plugin-datalabels'\r\nimport { Weapon, Filters, useKillStore } from '@/stores/kill'\r\nimport { Doughnut } from 'vue-chartjs'\r\nimport { defineComponent, PropType } from 'vue'\r\n\r\nChartJS.register(ArcElement, Tooltip, Legend, dataLabel)\r\n\r\nexport default defineComponent({\r\n name: 'PlayerChart',\r\n props: {\r\n filters: Object as PropType,\r\n playerHighlighted: String\r\n },\r\n emits: ['highlightPlayer'],\r\n components: {\r\n Doughnut\r\n },\r\n mounted () {\r\n this.refreshColors++\r\n },\r\n data: () => {\r\n return {\r\n store: useKillStore(),\r\n refreshColors: 0\r\n }\r\n },\r\n computed: {\r\n colors () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.refreshColors\r\n const colors = {} as { [key: string]: string }\r\n if (this.$refs.container) {\r\n const style = getComputedStyle(this.$refs.container as Element)\r\n colors.fg = style.getPropertyValue('--foreground')\r\n colors.bg = style.getPropertyValue('--bg-color')\r\n colors.orange = style.getPropertyValue('--orange')\r\n colors.cyan = style.getPropertyValue('--cyan')\r\n colors.yellow = style.getPropertyValue('--yellow')\r\n colors.green = style.getPropertyValue('--green')\r\n colors.purple = style.getPropertyValue('--purple')\r\n colors.red = style.getPropertyValue('--red')\r\n colors.pink = style.getPropertyValue('--pink')\r\n colors.currentLine = style.getPropertyValue('--current-line')\r\n } else {\r\n colors.fg = '#ffffff'\r\n }\r\n return colors\r\n },\r\n chart () {\r\n const colors = [\r\n 'cyan',\r\n 'green',\r\n 'orange',\r\n 'pink',\r\n 'purple',\r\n 'red',\r\n 'yellow'\r\n ]\r\n const chartData = {\r\n datasets: [\r\n {\r\n label: 'Weapons',\r\n labels: this.sortedWeaponList || ([] as string[]),\r\n borderColor: () => this.colors.fg,\r\n backgroundColor: (context: any) => {\r\n return this.colors[\r\n colors[(context.dataIndex * 3) % colors.length]\r\n ]\r\n },\r\n data: [] as number[]\r\n }\r\n ]\r\n }\r\n if (!this.sortedWeaponList) {\r\n return chartData\r\n }\r\n chartData.datasets[0].data = this.sortedWeaponList.map((e) => {\r\n if (!this.weapons) {\r\n return 0\r\n }\r\n return this.weapons[e].kills\r\n })\r\n return chartData\r\n },\r\n chartOptions () {\r\n // eslint-disable-next-line no-unused-expressions\r\n this.$props.playerHighlighted\r\n const options = {\r\n responsive: true,\r\n maintainAspectRatio: true,\r\n animation: { duration: 500 },\r\n layout: { autoPadding: false },\r\n plugins: {\r\n datalabels: {\r\n formatter: (value: any, context: any) => {\r\n return this.sortedWeaponList[context.dataIndex]\r\n },\r\n backgroundColor: (context: any) => {\r\n return context.dataset.backgroundColor(context)\r\n },\r\n borderColor: this.colors.fg,\r\n borderRadius: 25,\r\n borderWidth: 2,\r\n color: this.colors.bg,\r\n display: (context: any) => {\r\n return context.dataIndex === context.dataset.labels.length - 1\r\n ? true\r\n : 'auto'\r\n },\r\n padding: 6\r\n },\r\n tooltip: {\r\n callbacks: {\r\n label: (ctx: any) => {\r\n let label: string\r\n if (!this.sortedWeaponList) {\r\n label = ctx.dataset.labels[ctx.dataIndex]\r\n } else {\r\n label = this.sortedWeaponList[ctx.dataIndex]\r\n }\r\n label += ' (' + this.weapons[label].kills + ' kills)'\r\n return label\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return options\r\n },\r\n weapons (): { [key: string]: Weapon } {\r\n const { weapon: _, ...withoutWeapon } = this.filters || {}\r\n const data = this.store.getWeaponList(withoutWeapon)?.data\r\n if (!data) {\r\n this.store.fetchWeapons(withoutWeapon)\r\n return {}\r\n }\r\n return data\r\n },\r\n sortedWeaponList (): string[] {\r\n if (!this.weapons) return []\r\n const weapons = Object.keys(this.weapons)\r\n weapons.sort((a, b) => {\r\n if (Number(this.weapons[a].kills) < Number(this.weapons[b].kills)) {\r\n return -1\r\n }\r\n if (Number(this.weapons[a].kills) > Number(this.weapons[b].kills)) {\r\n return 1\r\n }\r\n return 0\r\n })\r\n return weapons\r\n }\r\n }\r\n})\r\n","import { render } from \"./WeaponChart.vue?vue&type=template&id=673fd0b6&scoped=true&ts=true\"\nimport script from \"./WeaponChart.vue?vue&type=script&lang=ts\"\nexport * from \"./WeaponChart.vue?vue&type=script&lang=ts\"\n\nimport \"./WeaponChart.vue?vue&type=style&index=0&id=673fd0b6&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-673fd0b6\"]])\n\nexport default __exports__","\r\nimport { Player, Weapon, Server, useKillStore, Filters } from '@/stores/kill'\r\nimport PlayerList from '@/components/PlayerList.vue'\r\nimport PlayerChart from '@/components/PlayerChart.vue'\r\nimport WeaponChart from '@/components/WeaponChart.vue'\r\nimport { defineComponent } from 'vue'\r\nimport VueMultiselect from 'vue-multiselect'\r\nimport 'vue-multiselect/dist/vue-multiselect.css'\r\n\r\nexport default defineComponent({\r\n name: 'PlayerView',\r\n components: {\r\n VueMultiselect, PlayerList, PlayerChart, WeaponChart\r\n },\r\n\r\n data () {\r\n return {\r\n model: { server: undefined, weapon: undefined } as unknown as {weapon:Weapon | Weapon[], server: (Server& {name?:string}) | (Server& {name?:string})[]},\r\n filters: {} as Filters,\r\n store: useKillStore(),\r\n playerHighlighted: undefined\r\n }\r\n },\r\n computed: {\r\n servers (): { [key: string]: Server } {\r\n const { server: _, player: _1, ...withoutServer } = this.filters\r\n const data = this.store.getServerList(withoutServer)?.data\r\n if (!data) {\r\n this.store.fetchServers(withoutServer)\r\n return {}\r\n }\r\n return data\r\n },\r\n groupedServers () {\r\n const hosts = [] as {id:string, servers:(Server& {name?:string})[] }[]\r\n Object.entries(this.servers).forEach((e) => {\r\n if (!hosts.find(host => host.id === e[1].host + 'sfdsdfsd')) hosts.push({ id: e[1].host + 'sfdsdfsd', servers: [] as Server[] })\r\n hosts.find(host => host.id === e[1].host + 'sfdsdfsd')?.servers.push({ name: e[0], ...e[1] })\r\n })\r\n return hosts\r\n },\r\n weapons (): { [key: string]: Weapon } {\r\n const { weapon: _, player: _1, ...withoutWeapons } = this.filters\r\n const data = this.store.getWeaponList(withoutWeapons)?.data\r\n if (!data) {\r\n this.store.fetchWeapons(withoutWeapons)\r\n return {}\r\n }\r\n return data\r\n },\r\n players (): { [key: string]: Player } {\r\n const { player: _, ...withoutPlayers } = this.filters\r\n const data = this.store.getPlayerList(withoutPlayers)?.data\r\n if (!data) {\r\n this.store.fetchPlayers(withoutPlayers)\r\n return {}\r\n }\r\n return data\r\n },\r\n sortedWeaponList (): string[] {\r\n if (!this.weapons) return []\r\n const weapons = Object.keys(this.weapons)\r\n return weapons.sort()\r\n },\r\n sortedServerList ():string[] {\r\n if (!this.servers) return []\r\n const servers = Object.keys(this.servers)\r\n return servers.sort()\r\n },\r\n sortedPlayerList (): string[] {\r\n if (!this.players) return []\r\n const players = Object.keys(this.players)\r\n return players.sort((a: string, b: string) => {\r\n if (!this.players) {\r\n return 0\r\n }\r\n if (this.players[a].username < this.players[b].username) {\r\n return -1\r\n }\r\n if (this.players[a].username > this.players[b].username) {\r\n return 1\r\n }\r\n return 0\r\n })\r\n }\r\n },\r\n watch: {\r\n model: {\r\n handler (newModel) {\r\n this.filters.server = newModel.server?.name\r\n this.filters.weapon = newModel.weapon\r\n },\r\n deep: true\r\n }\r\n }\r\n})\r\n","import { render } from \"./PlayerView.vue?vue&type=template&id=8bebdda4&scoped=true&ts=true\"\nimport script from \"./PlayerView.vue?vue&type=script&lang=ts\"\nexport * from \"./PlayerView.vue?vue&type=script&lang=ts\"\n\nimport \"./PlayerView.vue?vue&type=style&index=0&id=8bebdda4&scoped=true&lang=css\"\n\nimport exportComponent from \"C:\\\\Users\\\\legon\\\\Documents\\\\Code\\\\Tone\\\\ToneAPI_webclient\\\\node_modules\\\\vue-loader\\\\dist\\\\exportHelper.js\"\nconst __exports__ = /*#__PURE__*/exportComponent(script, [['render',render],['__scopeId',\"data-v-8bebdda4\"]])\n\nexport default __exports__","import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'\r\nimport HomeView from '../views/HomeView.vue'\r\nimport PlayerView from '../views/PlayerView.vue'\r\n\r\nconst routes: Array = [\r\n {\r\n path: '/',\r\n name: 'home',\r\n component: PlayerView\r\n }\r\n // {\r\n // path: '/players',\r\n // name: 'players',\r\n // component: PlayerView\r\n // },\r\n // {\r\n // path: '/about',\r\n // name: 'about',\r\n // // route level code-splitting\r\n // // this generates a separate chunk (about.[hash].js) for this route\r\n // // which is lazy-loaded when the route is visited.\r\n // component: () => import(/* webpackChunkName: \"about\" */ '../views/AboutView.vue')\r\n // }\r\n]\r\n\r\nconst router = createRouter({\r\n history: createWebHistory(process.env.BASE_URL),\r\n routes\r\n})\r\n\r\nexport default router\r\n","import { createApp } from 'vue'\r\nimport App from './App.vue'\r\nimport router from './router'\r\nimport { createPinia } from 'pinia'\r\n\r\nconst pinia = createPinia()\r\n\r\ncreateApp(App).use(pinia).use(router).mount('#app')\r\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId](module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","var deferred = [];\n__webpack_require__.O = function(result, chunkIds, fn, priority) {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every(function(key) { return __webpack_require__.O[key](chunkIds[j]); })) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = function(module) {\n\tvar getter = module && module.__esModule ?\n\t\tfunction() { return module['default']; } :\n\t\tfunction() { return module; };\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = function(exports, definition) {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }","// no baseURI\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t143: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = function(chunkId) { return installedChunks[chunkId] === 0; };\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = function(parentChunkLoadingFunction, data) {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some(function(id) { return installedChunks[id] !== 0; })) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunktoneapi_webclient\"] = self[\"webpackChunktoneapi_webclient\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [998], function() { return __webpack_require__(3870); })\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["_hoisted_1","_createStaticVNode","render","_ctx","_cache","$props","$setup","$data","$options","_component_router_link","_resolveComponent","_component_router_view","_openBlock","_createElementBlock","_Fragment","_createElementVNode","_createVNode","to","class","default","_withCtx","_createTextVNode","_","removeNullEntries","a","Object","fromEntries","entries","filter","e","undefined","objectEqual","b","assert","deepStrictEqual","useKillStore","defineStore","state","servers","players","weapons","maps","gamemodes","hosts","getters","getPlayerList","filters","find","getWeaponList","getServerList","actions","async","response","fetch","URLSearchParams","data","json","entry","this","push","defineComponent","setup","props","ctx","store","fetchPlayers","fetchServers","fetchWeapons","__exports__","id","_hoisted_2","_component_VueMultiselect","_component_PlayerList","_component_PlayerChart","_component_WeaponChart","selectLabel","deselectLabel","placeholder","modelValue","model","server","$event","options","groupedServers","group_label","multiple","name","label","weapon","sortedWeaponList","playerHighlighted","sortedPlayerList","username","onHighlightPlayer","player","_withScopeId","n","_pushScopeId","_popScopeId","_hoisted_3","onKeydown","args","selectNextPlayer","tabindex","onClick","sortPlayerList","_normalizeClass","sortingData","argument","_renderList","playerIdList","playerId","index","key","$emit","ref_for","ref","_toDisplayString","kills","deaths","Math","round","max","max_distance","total_distance","type","String","emits","direction","computed","withoutPlayer","watch","handler","newval","keys","slice","immediate","newElement","$refs","scrollIntoView","behavior","block","updated","element","methods","arg","sort","varA","varB","values","Home","Infinity","End","PageDown","PageUp","ArrowUp","ArrowDown","ArrowRight","ArrowLeft","includes","preventDefault","indexOf","nextIndex","length","_component_Scatter","chart","chartOptions","ChartJS","LinearScale","PointElement","LineElement","Tooltip","Legend","annotationPlugin","dataLabel","refreshColors","components","Scatter","mounted","colors","container","style","getComputedStyle","fg","getPropertyValue","bg","orange","cyan","currentLine","datasets","labels","borderColor","context","backgroundColor","pointRadius","pointStyle","hoverRadius","map","y","x","endX","endY","maxX","maxY","responsive","maintainAspectRatio","animation","duration","layout","autoPadding","scales","title","text","display","color","ticks","plugins","tooltip","callbacks","dataset","dataIndex","parsed","annotation","annotations","line","yMin","xMin","yMax","xMax","borderWidth","borderDash","legend","datalabels","formatter","value","borderRadius","align","anchor","clamp","onHover","native","target","cursor","cut","_component_Doughnut","ArcElement","Doughnut","yellow","green","purple","red","pink","chartData","padding","withoutWeapon","Number","VueMultiselect","PlayerList","PlayerChart","WeaponChart","_1","withoutServer","forEach","host","withoutWeapons","withoutPlayers","sortedServerList","newModel","deep","routes","path","component","PlayerView","router","createRouter","history","createWebHistory","process","pinia","createPinia","createApp","App","use","mount","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","module","__webpack_modules__","m","deferred","O","result","chunkIds","fn","priority","notFulfilled","i","fulfilled","j","every","splice","r","getter","__esModule","d","definition","o","defineProperty","enumerable","get","g","globalThis","Function","window","obj","prop","prototype","hasOwnProperty","call","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","some","chunkLoadingGlobal","self","bind","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file