Author SHA1 Message Date
legonzaur 0fbe38115f update hostname 2023-09-03 13:23:54 +02:00
legonzaur b827957d8a update og_image 2023-07-07 13:59:37 +02:00
legonzaur 5ca3c56564 fix locale on piechart not showing sometimes 2023-06-22 18:43:28 +02:00
legonzaur 9a5ba1178d merge gamemode and weapon into one reusable component 2023-06-22 18:38:51 +02:00
legonzaur 50adf2d9f0 fix chart width 2023-06-22 18:24:50 +02:00
legonzaur 979a65f443 add other gamemode localization 2023-06-22 10:38:11 +02:00
legonzaur 77116443ec update og image 2023-06-21 13:31:06 +02:00
legonzaur 8d1167fc64 add package lock 2023-06-21 13:24:27 +02:00
8 changed files with 12394 additions and 216 deletions
+12346
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 280 KiB

After

Width:  |  Height:  |  Size: 269 KiB

@@ -1,5 +1,5 @@
<template> <template>
<div class="gamemodeChart" ref="container"> <div class="chart" ref="container">
<LoadingBar v-if="progress !== 1" :value="progress"></LoadingBar> <LoadingBar v-if="progress !== 1" :value="progress"></LoadingBar>
<Doughnut :data="chart" :options="chartOptions" v-if="progress === 1" /> <Doughnut :data="chart" :options="chartOptions" v-if="progress === 1" />
</div> </div>
@@ -10,38 +10,48 @@ import { Chart as ChartJS, ArcElement, Tooltip, Legend, ChartData, ChartOptions
import dataLabel from 'chartjs-plugin-datalabels' import dataLabel from 'chartjs-plugin-datalabels'
import { Weapon, Filter, useKillStore } from '@/stores/kill' import { Weapon, Filter, useKillStore } from '@/stores/kill'
import { Doughnut } from 'vue-chartjs' import { Doughnut } from 'vue-chartjs'
import { defineComponent, PropType, Ref, unref } from 'vue' import { defineComponent, PropType, Ref, triggerRef, unref } from 'vue'
import gamemodes from '../stores/gamemodes.json'
import LoadingBar from './LoadingBar.vue' import LoadingBar from './LoadingBar.vue'
ChartJS.register(ArcElement, Tooltip, Legend, dataLabel) ChartJS.register(ArcElement, Tooltip, Legend, dataLabel)
export default defineComponent({ export default defineComponent({
name: 'GamemodeChart', name: 'PieChart',
props: { props: {
filters: Object as PropType<Filter>, filters: Object as PropType<Filter>,
playerHighlighted: String playerHighlighted: String,
type: Object as PropType<'server' | 'player' | 'weapon' | 'map' | 'gamemode'>
}, },
emits: ['highlightPlayer'], emits: ['highlightPlayer'],
components: { components: {
Doughnut, LoadingBar Doughnut, LoadingBar
}, },
created () {
// eslint-disable-next-line no-extra-bind
import(`../stores/${this.type}s.json`).then((e => { this.locale = e }).bind(this))
},
mounted () { mounted () {
this.refreshColors++ this.refreshColors++
}, },
data: () => { data: () => {
return { return {
store: useKillStore(), store: useKillStore(),
refreshColors: 0 refreshColors: 0,
locale: {} as {[key:string]:string}
} }
}, },
computed: { computed: {
progress () { progress () {
const filter = new Filter(this.filters) const filter = new Filter(this.filters)
delete filter.gamemode if (this.type === undefined) return 0
const data = this.store.getList('gamemodes', filter)?.value if (!(['server', 'player', 'weapon', 'map', 'gamemode'].includes(this.type))) return 0
if (!data) return this.store.fetch('gamemodes', filter).value.progress.value if (Object.keys(this.locale).length === 0) return 0
const type = this.type as 'server' | 'player' | 'weapon' | 'map' | 'gamemode'
if (this.type !== undefined) delete filter[type]
const data = this.store.getList(`${type}s`, filter)?.value
if (!data) return this.store.fetch(`${type}s`, filter).value.progress.value
return data.progress.value return data.progress.value
}, },
colors () { colors () {
@@ -112,8 +122,7 @@ export default defineComponent({
datalabels: { datalabels: {
formatter: (value, context) => { formatter: (value, context) => {
const weaponId = this.sortedList[context.dataIndex] const weaponId = this.sortedList[context.dataIndex]
// if (!(weapons as {[key:string]:string})[weaponId]) console.log(weaponId) return this.locale[weaponId] || weaponId
return (gamemodes as { [key: string]: string })[weaponId] || weaponId
}, },
backgroundColor: (context) => { backgroundColor: (context) => {
return context.dataset.backgroundColor(context, options) return context.dataset.backgroundColor(context, options)
@@ -149,9 +158,11 @@ export default defineComponent({
}, },
values (): { [key: string]: Ref<Weapon> } { values (): { [key: string]: Ref<Weapon> } {
const filter = new Filter({ ...this.filters, player: this.playerHighlighted }) const filter = new Filter({ ...this.filters, player: this.playerHighlighted })
delete filter.gamemode if (this.type === undefined) return {}
const data = this.store.getList('gamemodes', filter)?.value.data if (!(['server', 'player', 'weapon', 'map', 'gamemode'].includes(this.type))) return {}
if (!data) return this.store.fetch('gamemodes', filter).value.data const type = this.type as 'server' | 'player' | 'weapon' | 'map' | 'gamemode'
const data = this.store.getList(`${type}s`, filter)?.value.data
if (!data) return this.store.fetch(`${type}s`, filter).value.data
return data return data
}, },
sortedList (): string[] { sortedList (): string[] {
@@ -173,9 +184,8 @@ export default defineComponent({
</script> </script>
<style scoped> <style scoped>
.weaponChart { .chart {
width: calc(min(50vw, 50vh) - 3em); width: 100%;
height: calc(min(50vw, 50vh) - 3em);
} }
@media only screen and (max-width: 922px) { @media only screen and (max-width: 922px) {
-186
View File
@@ -1,186 +0,0 @@
<template>
<div class="weaponChart" ref="container">
<LoadingBar v-if="progress !== 1" :value="progress"></LoadingBar>
<Doughnut :data="chart" :options="chartOptions" v-if="progress === 1" />
</div>
</template>
<script lang="ts">
import { Chart as ChartJS, ArcElement, Tooltip, Legend, ChartData, ChartOptions } from 'chart.js'
import dataLabel from 'chartjs-plugin-datalabels'
import { Weapon, Filter, useKillStore } from '@/stores/kill'
import { Doughnut } from 'vue-chartjs'
import { defineComponent, PropType, Ref, unref } from 'vue'
import weapons from '../stores/weapons.json'
import LoadingBar from './LoadingBar.vue'
ChartJS.register(ArcElement, Tooltip, Legend, dataLabel)
export default defineComponent({
name: 'WeaponChart',
props: {
filters: Object as PropType<Filter>,
playerHighlighted: String
},
emits: ['highlightPlayer'],
components: {
Doughnut, LoadingBar
},
mounted () {
this.refreshColors++
},
data: () => {
return {
store: useKillStore(),
refreshColors: 0
}
},
computed: {
progress () {
const filter = new Filter(this.filters)
delete filter.weapon
const data = this.store.getList('weapons', filter)?.value
if (!data) return this.store.fetch('weapons', filter).value.progress.value
return data.progress.value
},
colors () {
// eslint-disable-next-line no-unused-expressions
this.refreshColors
const colors = {} as { [key: string]: string }
if (this.$refs.container) {
const style = getComputedStyle(this.$refs.container as Element)
colors.fg = style.getPropertyValue('--foreground')
colors.bg = style.getPropertyValue('--bg-color')
colors.orange = style.getPropertyValue('--orange')
colors.cyan = style.getPropertyValue('--cyan')
colors.yellow = style.getPropertyValue('--yellow')
colors.green = style.getPropertyValue('--green')
colors.purple = style.getPropertyValue('--purple')
colors.red = style.getPropertyValue('--red')
colors.pink = style.getPropertyValue('--pink')
colors.currentLine = style.getPropertyValue('--current-line')
} else {
colors.fg = '#ffffff'
}
return colors
},
chart (): ChartData<'doughnut', number[]> {
const colors = [
'cyan',
'green',
'orange',
'pink',
'purple',
'red',
'yellow'
]
const chartData: ChartData<'doughnut', number[]> = {
datasets: [
{
label: 'Weapons',
borderColor: () => this.colors.fg,
backgroundColor: (context) => {
return this.colors[
colors[(context.dataIndex * 3) % colors.length]
]
},
data: [] as number[]
}
]
}
if (!this.sortedWeaponList) {
return chartData
}
chartData.datasets[0].data = this.sortedWeaponList.map((e) => {
if (!this.weapons) {
return 0
}
return this.weapons[e].value.kills
})
return chartData
},
chartOptions (): ChartOptions<'doughnut'> {
// eslint-disable-next-line no-unused-expressions
this.$props.playerHighlighted
const options: ChartOptions<'doughnut'> = {
responsive: true,
maintainAspectRatio: true,
animation: { duration: 500 },
layout: { autoPadding: false },
plugins: {
datalabels: {
formatter: (value, context) => {
const weaponId = this.sortedWeaponList[context.dataIndex]
// if (!(weapons as {[key:string]:string})[weaponId]) console.log(weaponId)
return (weapons as { [key: string]: string })[weaponId] || weaponId
},
backgroundColor: (context) => {
return context.dataset.backgroundColor(context, options)
},
borderColor: this.colors.fg,
borderRadius: 25,
borderWidth: 2,
color: this.colors.bg,
display: (context) => {
return context.dataIndex === context.dataset.data.length - 1
? true
: 'auto'
},
padding: 6
},
tooltip: {
callbacks: {
label: (ctx: any) => {
let label: string
if (!this.sortedWeaponList) {
label = ctx.dataset.labels[ctx.dataIndex]
} else {
label = this.sortedWeaponList[ctx.dataIndex]
}
label += ' (' + this.weapons[label].value.kills + ' kills)'
return label
}
}
}
}
}
return options
},
weapons (): { [key: string]: Ref<Weapon> } {
const filter = new Filter({ ...this.filters, player: this.playerHighlighted })
delete filter.weapon
const data = this.store.getList('weapons', filter)?.value.data
if (!data) return this.store.fetch('weapons', filter).value.data
return data
},
sortedWeaponList (): string[] {
if (!this.weapons) return []
const weapons = Object.keys(this.weapons).filter(e => unref(this.weapons[e]).kills > 0)
weapons.sort((a, b) => {
if (Number(this.weapons[a].value.kills) < Number(unref(this.weapons[b]).kills)) {
return -1
}
if (Number(this.weapons[a].value.kills) > Number(unref(this.weapons[b]).kills)) {
return 1
}
return 0
})
return weapons
}
}
})
</script>
<style scoped>
.weaponChart {
width: calc(min(50vw, 50vh) - 3em);
height: calc(min(50vw, 50vh) - 3em);
}
@media only screen and (max-width: 922px) {
canvas {
display: none !important;
}
}
</style>
+1 -1
View File
@@ -44,7 +44,7 @@ type websocketData = {
// dev stuff // dev stuff
const store = useKillStore() const store = useKillStore()
const socket = new WebSocket('wss://tone.sleepycat.date/v2/client/websocket') const socket = new WebSocket('wss://toneapi.ovh/v2/client/websocket')
socket.onmessage = function (e) { socket.onmessage = function (e) {
if (e.data === 'ping') return socket.send('pong') if (e.data === 'ping') return socket.send('pong')
const data = JSON.parse(e.data) const data = JSON.parse(e.data)
+11 -2
View File
@@ -15,5 +15,14 @@
"sns": "Stick and Stones", "sns": "Stick and Stones",
"gg": "GunGame", "gg": "GunGame",
"fd": "Frontier Defense", "fd": "Frontier Defense",
"ffa": "Free For All" "ffa": "Free For All",
} "chamber": "One in the Chamber",
"fastball": "Fastball",
"ctf_comp": "Competitive CTF",
"hidden":"The Hidden",
"hs":"Hide and Seek",
"inf":"Infection",
"kr":"Amped Killrace",
"tffa":"Titan FFA",
"tt":"Titan Tag"
}
+1 -1
View File
@@ -181,7 +181,7 @@ export const useKillStore = defineStore('kill', {
// console.log(isRef(entry), this.$state.killData) // console.log(isRef(entry), this.$state.killData)
} }
fetchWithLoading( fetchWithLoading(
`https://tone.sleepycat.date/v2/client/${type}?` + `https://toneapi.ovh/v2/client/${type}?` +
filter?.toURLSearchParams() ?? '', filter?.toURLSearchParams() ?? '',
(progress) => { (progress) => {
if (entry && progress !== 1 && unref(entry).progress.value !== 1) { if (entry && progress !== 1 && unref(entry).progress.value !== 1) {
+8 -9
View File
@@ -80,15 +80,16 @@
:playerHighlighted="playerHighlighted?.id" :playerHighlighted="playerHighlighted?.id"
> >
</PlayerChart> </PlayerChart>
<WeaponChart <PieChart
:filters="{ player: playerHighlighted?.id, ...filters }" :filters="{ player: playerHighlighted?.id, ...filters }"
:playerHighlighted="playerHighlighted?.id" :playerHighlighted="playerHighlighted?.id"
> type="weapon"
</WeaponChart> ></PieChart>
<GamemodeChart <PieChart
:filters="{ player: playerHighlighted?.id, ...filters }" :filters="{ player: playerHighlighted?.id, ...filters }"
:playerHighlighted="playerHighlighted?.id" :playerHighlighted="playerHighlighted?.id"
></GamemodeChart> type="gamemode"
></PieChart>
</div> </div>
</template> </template>
@@ -96,8 +97,7 @@
import { Player, Weapon, Server, Kill, useKillStore, Filter } from '@/stores/kill' import { Player, Weapon, Server, Kill, useKillStore, Filter } from '@/stores/kill'
import PlayerList from '@/components/PlayerList.vue' import PlayerList from '@/components/PlayerList.vue'
import PlayerChart from '@/components/PlayerChart.vue' import PlayerChart from '@/components/PlayerChart.vue'
import WeaponChart from '@/components/WeaponChart.vue' import PieChart from '@/components/PieChart.vue'
import GamemodeChart from '@/components/GamemodeChart.vue'
import { Ref, defineComponent, unref } from 'vue' import { Ref, defineComponent, unref } from 'vue'
import VueMultiselect from 'vue-multiselect' import VueMultiselect from 'vue-multiselect'
import 'vue-multiselect/dist/vue-multiselect.css' import 'vue-multiselect/dist/vue-multiselect.css'
@@ -115,8 +115,7 @@ export default defineComponent({
VueMultiselect, VueMultiselect,
PlayerList, PlayerList,
PlayerChart, PlayerChart,
WeaponChart, PieChart
GamemodeChart
}, },
data () { data () {