New tierlists :)
This commit is contained in:
83
frontend/components/tierlist/Chart.vue
Normal file
83
frontend/components/tierlist/Chart.vue
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { Chart as ChartJS, Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale, plugins, scales } from 'chart.js'
|
||||||
|
import { Bar } from 'vue-chartjs'
|
||||||
|
|
||||||
|
// Register
|
||||||
|
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
data: Array<Array<{champion: Champion, lane: LaneData}>>
|
||||||
|
}>()
|
||||||
|
|
||||||
|
const labels: Array<string> = []
|
||||||
|
const pickrates: Array<number> = []
|
||||||
|
const images: Array<string> = []
|
||||||
|
const backgroundColors: Array<string> = []
|
||||||
|
const tier_colors = ["#ff7f7e", "#ffbf7f", "#ffdf80", "#feff7f", "#beff7f"]
|
||||||
|
const datasets = []
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
let colorIndex = 0
|
||||||
|
for(let tier of props.data) {
|
||||||
|
for(let {champion: champion, lane: lane} of tier) {
|
||||||
|
if(count > 35) break;
|
||||||
|
|
||||||
|
labels.push(champion.name)
|
||||||
|
pickrates.push(lane.pickrate * 100)
|
||||||
|
images.push(CDRAGON_BASE + mapPath(champion.squarePortraitPath))
|
||||||
|
// backgroundColors.push('#B7B8E1')
|
||||||
|
backgroundColors.push(tier_colors[colorIndex])
|
||||||
|
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
colorIndex++
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const chartData = ref({
|
||||||
|
labels: labels,
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'Pickrate',
|
||||||
|
backgroundColor: backgroundColors,
|
||||||
|
barPercentage: 1.0,
|
||||||
|
data: pickrates,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
})
|
||||||
|
const chartOptions = ref({
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
ticks: {
|
||||||
|
callback: (() => "")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const chartPlugins = [{
|
||||||
|
id: "image-draw",
|
||||||
|
afterDraw: ((chart: any) => {
|
||||||
|
const ctx : CanvasRenderingContext2D = chart.ctx
|
||||||
|
var xAxis = chart.scales.x;
|
||||||
|
xAxis.ticks.forEach((value: any, index: number) => {
|
||||||
|
var x = xAxis.getPixelForTick(index)
|
||||||
|
var image = new Image()
|
||||||
|
image.src = images[index]
|
||||||
|
ctx.drawImage(image, x - 14, xAxis.bottom - 28, 28, 28)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}]
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<Bar :data="chartData" :options="chartOptions" :plugins="chartPlugins" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
defineProps<{
|
defineProps<{
|
||||||
title: string
|
title: string
|
||||||
tier: Array<Champion>
|
tier: Array<{champion: Champion, lane: LaneData}>
|
||||||
}>()
|
}>()
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ defineProps<{
|
|||||||
<div style="display: flex; align-items: center;">
|
<div style="display: flex; align-items: center;">
|
||||||
<h2 class="tierlist-tier-title">{{ title }}</h2>
|
<h2 class="tierlist-tier-title">{{ title }}</h2>
|
||||||
<div class="tierlist-tier-container">
|
<div class="tierlist-tier-container">
|
||||||
<NuxtLink v-for="champion in tier" :to="'/champion/' + champion.alias.toLowerCase()">
|
<NuxtLink v-for="{champion: champion} in tier" :to="'/champion/' + champion.alias.toLowerCase()">
|
||||||
<div class="champion-img-container">
|
<div class="champion-img-container">
|
||||||
<NuxtImg class="champion-img" :src="CDRAGON_BASE + mapPath(champion.squarePortraitPath)" :alt="champion.name"/>
|
<NuxtImg class="champion-img" :src="CDRAGON_BASE + mapPath(champion.squarePortraitPath)" :alt="champion.name"/>
|
||||||
</div>
|
</div>
|
||||||
30
frontend/package-lock.json
generated
30
frontend/package-lock.json
generated
@@ -10,10 +10,12 @@
|
|||||||
"@nuxt/fonts": "^0.10.2",
|
"@nuxt/fonts": "^0.10.2",
|
||||||
"@nuxt/image": "^1.8.1",
|
"@nuxt/image": "^1.8.1",
|
||||||
"@nuxtjs/seo": "^2.0.2",
|
"@nuxtjs/seo": "^2.0.2",
|
||||||
|
"chart.js": "^4.4.7",
|
||||||
"mongodb": "^6.10.0",
|
"mongodb": "^6.10.0",
|
||||||
"nuxt": "^3.14.1592",
|
"nuxt": "^3.14.1592",
|
||||||
"svg-dom-arrows": "^2.3.0",
|
"svg-dom-arrows": "^2.3.0",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
|
"vue-chartjs": "^5.3.2",
|
||||||
"vue-router": "latest"
|
"vue-router": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -1095,6 +1097,12 @@
|
|||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@kurkle/color": {
|
||||||
|
"version": "0.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz",
|
||||||
|
"integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@kwsites/file-exists": {
|
"node_modules/@kwsites/file-exists": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@kwsites/file-exists/-/file-exists-1.1.1.tgz",
|
||||||
@@ -4367,6 +4375,18 @@
|
|||||||
"integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
|
"integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/chart.js": {
|
||||||
|
"version": "4.4.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.7.tgz",
|
||||||
|
"integrity": "sha512-pwkcKfdzTMAU/+jNosKhNL2bHtJc/sSmYgVbuGTEDhzkrhmyihmP7vUc/5ZK9WopidMDHNe3Wm7jOd/WhuHWuw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@kurkle/color": "^0.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"pnpm": ">=8"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/cheerio": {
|
"node_modules/cheerio": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
|
||||||
@@ -12002,6 +12022,16 @@
|
|||||||
"ufo": "^1.5.4"
|
"ufo": "^1.5.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vue-chartjs": {
|
||||||
|
"version": "5.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-chartjs/-/vue-chartjs-5.3.2.tgz",
|
||||||
|
"integrity": "sha512-NrkbRRoYshbXbWqJkTN6InoDVwVb90C0R7eAVgMWcB9dPikbruaOoTFjFYHE/+tNPdIe6qdLCDjfjPHQ0fw4jw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"peerDependencies": {
|
||||||
|
"chart.js": "^4.1.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/vue-devtools-stub": {
|
"node_modules/vue-devtools-stub": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/vue-devtools-stub/-/vue-devtools-stub-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/vue-devtools-stub/-/vue-devtools-stub-0.1.0.tgz",
|
||||||
|
|||||||
@@ -13,10 +13,12 @@
|
|||||||
"@nuxt/fonts": "^0.10.2",
|
"@nuxt/fonts": "^0.10.2",
|
||||||
"@nuxt/image": "^1.8.1",
|
"@nuxt/image": "^1.8.1",
|
||||||
"@nuxtjs/seo": "^2.0.2",
|
"@nuxtjs/seo": "^2.0.2",
|
||||||
|
"chart.js": "^4.4.7",
|
||||||
"mongodb": "^6.10.0",
|
"mongodb": "^6.10.0",
|
||||||
"nuxt": "^3.14.1592",
|
"nuxt": "^3.14.1592",
|
||||||
"svg-dom-arrows": "^2.3.0",
|
"svg-dom-arrows": "^2.3.0",
|
||||||
"vue": "latest",
|
"vue": "latest",
|
||||||
|
"vue-chartjs": "^5.3.2",
|
||||||
"vue-router": "latest"
|
"vue-router": "latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|||||||
@@ -21,28 +21,37 @@ const champions = championsData.value.slice(1).filter((champion) => {
|
|||||||
acc || (current.data.toLowerCase() == lane.toLowerCase()), false)
|
acc || (current.data.toLowerCase() == lane.toLowerCase()), false)
|
||||||
})
|
})
|
||||||
|
|
||||||
function tierFromPickrate(pickrate: number, previousTier: number) {
|
const allChampions = champions.map((x) => {
|
||||||
return champions.filter((champion) => {
|
const championData : ChampionData = infoMap.get(x.alias.toLowerCase())!!
|
||||||
const championData : ChampionData | undefined = infoMap.get(champion.alias.toLowerCase())
|
|
||||||
if(championData == undefined) return false;
|
|
||||||
|
|
||||||
let currentLane = championData.lanes[0]
|
let currentLane = championData.lanes[0]
|
||||||
for(let championLane of championData.lanes) {
|
for(let championLane of championData.lanes) {
|
||||||
if(championLane.data.toLowerCase() == lane.toLowerCase()) {
|
if(championLane.data.toLowerCase() == lane.toLowerCase()) {
|
||||||
currentLane = championLane
|
currentLane = championLane
|
||||||
break
|
break
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return currentLane.pickrate > pickrate && currentLane.pickrate < previousTier
|
return {lane: currentLane, champion: x}
|
||||||
}).sort((a, b) => infoMap.get(b.alias.toLowerCase())?.pickrate!! - infoMap.get(a.alias.toLowerCase())?.pickrate!!)
|
}).sort((a, b) => b.lane.pickrate - a.lane.pickrate)
|
||||||
|
|
||||||
|
const p_min = Math.min(...allChampions.map((x) => x.lane.pickrate))
|
||||||
|
const p_max = Math.max(...allChampions.map((x) => x.lane.pickrate))
|
||||||
|
|
||||||
|
allChampions.map((x) => (x as {lane: LaneData, champion: Champion, scaledPickrate: number}).scaledPickrate = (x.lane.pickrate - p_min)/(p_max - p_min))
|
||||||
|
allChampions.sort((a, b) => b.lane.pickrate - a.lane.pickrate)
|
||||||
|
function tierFromScaledPickrate(min: number, max: number) {
|
||||||
|
return (allChampions as Array<{lane: LaneData, champion: Champion, scaledPickrate: number}>)
|
||||||
|
.filter(({scaledPickrate: scaledPickrate}) => {
|
||||||
|
return scaledPickrate > min && scaledPickrate <= max
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const s_tier = tierFromPickrate(0.22, 1)
|
const s_tier = tierFromScaledPickrate(0.9, 1)
|
||||||
const a_tier = tierFromPickrate(0.15, 0.22)
|
const a_tier = tierFromScaledPickrate(0.7, 0.9)
|
||||||
const b_tier = tierFromPickrate(0.10, 0.15)
|
const b_tier = tierFromScaledPickrate(0.5, 0.7)
|
||||||
const c_tier = tierFromPickrate(0.05, 0.10)
|
const c_tier = tierFromScaledPickrate(0.3, 0.5)
|
||||||
const d_tier = tierFromPickrate(0, 0.05)
|
const d_tier = tierFromScaledPickrate(0.1, 0.3)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@@ -67,6 +76,8 @@ const d_tier = tierFromPickrate(0, 0.05)
|
|||||||
<TierlistTier title="C" :tier="c_tier" />
|
<TierlistTier title="C" :tier="c_tier" />
|
||||||
<TierlistTier title="D" :tier="d_tier" />
|
<TierlistTier title="D" :tier="d_tier" />
|
||||||
|
|
||||||
|
<TierlistChart style="margin-left: 100px; margin-right: 100px; margin-bottom: 100px; margin-top: 40px" :data="[s_tier, a_tier, b_tier, c_tier, d_tier]" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user