373 lines
10 KiB
Vue
373 lines
10 KiB
Vue
<template>
|
|
<div class="side-info">
|
|
|
|
<div v-if="props.player_meta.most_mates" class="side-info-box most-played-with">
|
|
<div class="heading">
|
|
<h5>Most played with</h5>
|
|
</div>
|
|
<hr>
|
|
<ul v-for="mate in props.player_meta.most_mates" :key="mate.player.steamid64" class="list-unstyled">
|
|
<li @click="GoToPlayer(mate.player.vanity_url || mate.player.steamid64)">
|
|
<span class="start">
|
|
<img :class="mate.player.tracked ? 'tracked' : ''" :src="constructAvatarUrl(mate.player.avatar)"
|
|
:title="mate.player.tracked ? 'Tracked' : ''" alt="Player avatar">
|
|
<span class="text">{{ mate.player.name }}</span>
|
|
</span>
|
|
<span class="end">
|
|
{{ mate.total }}
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-else class="side-info-box most-played-with">
|
|
<div class="heading">
|
|
<h5>Most played with</h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-if="props.player_meta.best_mates" class="side-info-box best-mate">
|
|
<div class="heading">
|
|
<h5>Best Mate <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul v-for="mate in props.player_meta.best_mates" :key="mate.player.steamid64" class="list-unstyled">
|
|
<li @click="GoToPlayer(mate.player.vanity_url || mate.player.steamid64)">
|
|
<span class="start">
|
|
<img :class="mate.player.tracked ? 'tracked' : ''" :src="constructAvatarUrl(mate.player.avatar)"
|
|
:title="mate.player.tracked ? 'Tracked' : ''" alt="Player avatar">
|
|
<span class="text">{{ mate.player.name }}</span>
|
|
</span>
|
|
<span class="end">
|
|
{{ (mate.win_rate * 100).toFixed(0) }} %
|
|
<span v-if="mate.total" class="total text-muted">({{ mate.total }})</span>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-else-if="props.player_meta.most_mates && props.player_meta.most_mates[0].total === 1" class="side-info-box best-mate">
|
|
<div class="heading">
|
|
<h5>Best Mate <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="col-11">Not enough Data</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-else class="side-info-box best-mate">
|
|
<div class="heading">
|
|
<h5>Best Mate <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-if="props.player_meta.eq_map && props.player_meta.weapon_dmg" class="side-info-box preferred-weapons">
|
|
<div class="heading">
|
|
<h5>Weapons <span class="text-muted">(by dmg)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul v-for="(id, key) in data.best_weapons" :key="id[0]" class="list-unstyled">
|
|
<li>
|
|
<span class="start">
|
|
<span class="text">{{ id[0] }}</span>
|
|
</span>
|
|
<span :title="id[0] + ' - ' + id[1] + ' dmg'" class="end">
|
|
<span :class="'dmg-chart-' + key">
|
|
{{ id[1] }}
|
|
</span>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
{{ setDmgGraphWidth() }}
|
|
</div>
|
|
|
|
<div v-else class="side-info-box preferred-weapons">
|
|
<div class="heading">
|
|
<h5>Weapons <span class="text-muted">(by dmg)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-if="props.player_meta.win_maps" class="side-info-box best-map">
|
|
<div class="heading">
|
|
<h5>Best Map <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul v-for="map in data.best_maps" :key="map[0]" class="list-unstyled">
|
|
<li>
|
|
<span class="start">
|
|
<img :src="require('../assets/images/map_icons/map_icon_' + map[0] + '.svg')" alt="Player avatar">
|
|
<span class="text">{{ FixMapName(map[0]) }}</span>
|
|
</span>
|
|
<span class="end">
|
|
{{ (map[1] * 100).toFixed(0) }} %
|
|
<span v-if="props.player_meta.total_maps[map[0]]"
|
|
class="total text-muted">({{ props.player_meta.total_maps[map[0]] }})</span>
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-else-if="props.player_meta.total_maps && !props.player_meta.win_maps" class="side-info-box best-map">
|
|
<div class="heading">
|
|
<h5>Best Map <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="col-11">Not enough Data</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div v-else class="side-info-box best-map">
|
|
<div class="heading">
|
|
<h5>Best Map <span class="text-muted">(by winrate)</span></h5>
|
|
</div>
|
|
<hr>
|
|
<ul class="list-unstyled placeholder-glow">
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
<li class="placeholder col-11"></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
import {constructAvatarUrl, FixMapName, GoToPlayer, sortObjectValue} from "@/utils";
|
|
import {reactive, ref, watch} from "vue";
|
|
|
|
export default {
|
|
name: "PlayerSideInfo",
|
|
props: {
|
|
player_meta: {
|
|
type: Object,
|
|
required: true
|
|
}
|
|
},
|
|
setup(props) {
|
|
const displayCounter = 3
|
|
|
|
const data = reactive({
|
|
best_maps: [],
|
|
best_weapons_tmp: [],
|
|
best_weapons: []
|
|
})
|
|
|
|
const mapWeaponDamage = () => {
|
|
if (props.player_meta.eq_map && props.player_meta.weapon_dmg) {
|
|
Object.keys(props.player_meta.eq_map).forEach((key) => {
|
|
for (const id in props.player_meta.weapon_dmg) {
|
|
Object.keys(props.player_meta.weapon_dmg[id]).forEach((k) => {
|
|
if (k === 'eq') {
|
|
if (props.player_meta.weapon_dmg[id][k] === key * 1) {
|
|
data.best_weapons_tmp.push([props.player_meta.eq_map[key], props.player_meta.weapon_dmg[id]['dmg']])
|
|
}
|
|
}
|
|
})
|
|
}
|
|
})
|
|
|
|
data.best_weapons_tmp.sort((a, b) => {
|
|
return b[1] - a[1]
|
|
})
|
|
|
|
data.best_weapons = data.best_weapons_tmp
|
|
data.best_weapons_tmp = []
|
|
}
|
|
}
|
|
|
|
const setDmgGraphWidth = () => {
|
|
setTimeout(() => {
|
|
let weaponsContainer
|
|
const dmg100 = ref(0)
|
|
const dmg = ref(0)
|
|
|
|
for (let i = 0; i <= 4; i++) {
|
|
weaponsContainer = document.querySelector('.dmg-chart-' + i)
|
|
if (weaponsContainer !== null) {
|
|
if (i === 0) {
|
|
dmg100.value = weaponsContainer.innerHTML * 1
|
|
weaponsContainer.style.width = '100%'
|
|
}
|
|
|
|
dmg.value = weaponsContainer.innerHTML * 1
|
|
weaponsContainer.style.width = dmg.value * 100 / dmg100.value + '%'
|
|
}
|
|
}
|
|
}, 100)
|
|
}
|
|
|
|
watch(() => props.player_meta, () => {
|
|
mapWeaponDamage()
|
|
|
|
data.best_maps = sortObjectValue(props.player_meta.win_maps, 'desc')
|
|
|
|
if (data.best_maps.length > displayCounter)
|
|
data.best_maps.splice(displayCounter, data.best_maps.length - displayCounter)
|
|
})
|
|
|
|
return {props, data, setDmgGraphWidth, GoToPlayer, constructAvatarUrl, FixMapName}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.side-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 1rem;
|
|
|
|
width: 100%;
|
|
height: auto;
|
|
margin-top: 30px;
|
|
|
|
.placeholder {
|
|
height: 25px;
|
|
padding: 0 10px !important;
|
|
margin: 14px auto !important;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.side-info-box {
|
|
width: 100%;
|
|
height: auto;
|
|
background: rgba(20, 20, 20, .8);
|
|
border: 1px solid rgba(white, .3);
|
|
border-radius: 5px;
|
|
}
|
|
|
|
ol, ul, dl {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.best-mate,
|
|
.preferred-weapons,
|
|
.most-played-with,
|
|
.best-map {
|
|
.heading {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
height: 30px;
|
|
|
|
h5 {
|
|
font-size: 1rem;
|
|
margin: 0;
|
|
padding: 0;
|
|
}
|
|
}
|
|
|
|
hr {
|
|
margin: 0 0 5px 0;
|
|
border-color: rgba(white, .3);
|
|
}
|
|
|
|
ul li {
|
|
line-height: 25px;
|
|
font-size: .9rem;
|
|
padding: 0 10px;
|
|
margin: 10px 0;
|
|
cursor: pointer;
|
|
|
|
display: flex;
|
|
justify-content: space-between;
|
|
gap: 1rem;
|
|
|
|
.start {
|
|
width: 50%;
|
|
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
|
|
.tracked {
|
|
font-size: .8rem;
|
|
margin-right: 5px;
|
|
}
|
|
|
|
img {
|
|
width: 25px;
|
|
height: 25px;
|
|
border-radius: 50%;
|
|
margin-right: 5px;
|
|
margin-left: 5px;
|
|
|
|
&.tracked {
|
|
border: 2px solid var(--bs-success);
|
|
}
|
|
}
|
|
}
|
|
|
|
.end {
|
|
display: flex;
|
|
width: 45%;
|
|
justify-content: flex-end;
|
|
align-items: flex-end;
|
|
}
|
|
}
|
|
}
|
|
|
|
.best-map, .best-mate {
|
|
ul li {
|
|
.start {
|
|
width: 75%;
|
|
}
|
|
|
|
.end {
|
|
.total {
|
|
padding-left: 5px;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.preferred-weapons,
|
|
.best-map {
|
|
ul li {
|
|
cursor: default;
|
|
}
|
|
}
|
|
|
|
.preferred-weapons {
|
|
.end {
|
|
position: relative;
|
|
|
|
@for $i from 0 through 3 {
|
|
.dmg-chart-#{$i} {
|
|
position: absolute;
|
|
background: rgba(150, 50, 50, 1);
|
|
border-radius: 15px;
|
|
color: transparent;
|
|
user-select: none;
|
|
cursor: help;
|
|
|
|
&:hover {
|
|
background: rgba(220, 50, 50, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|