Lint and format
This commit is contained in:
@@ -1,44 +1,44 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
</script>
|
||||
<script setup lang="ts"></script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>About</Title>
|
||||
</Head>
|
||||
<Head>
|
||||
<Title>About</Title>
|
||||
</Head>
|
||||
|
||||
<div class="about-main-content">
|
||||
<div class="about-main-content">
|
||||
<NavBar :tierlist-list="true" />
|
||||
|
||||
<div style="width: fit-content; margin: auto;">
|
||||
<Logo />
|
||||
|
||||
<div style="margin-top: 20px;">
|
||||
<h1>About</h1>
|
||||
<h3 style="margin-top: 20px;">BuildPath: a tool for League of Legends champions runes and build paths.</h3>
|
||||
<h3 style="margin-top: 10px;">Copyright (C) Valentin Haudiquet (@vhaudiquet)</h3>
|
||||
<h3 style="margin-top: 20px;">Acknowledgments:</h3>
|
||||
<h3>- Sarah Emery, for the feedback on the designs and code</h3>
|
||||
<h3>- Martin Andrieux, for the nice algorithms :)</h3>
|
||||
<h3>- Paul Chaurand, for the feedback on the league data organization</h3>
|
||||
<h3>- Nathan Mérillon, for the tierlists ideas</h3>
|
||||
<h3>- Jean-Baptiste Döderlein, for the feedback on the mobile design</h3>
|
||||
<h3 style="margin-top: 20px;">Libraries used:</h3>
|
||||
<h3>Vue.JS, Nuxt.JS, Chart.JS, svg-dom-arrows</h3>
|
||||
<h2 style="font-size: 1rem; font-weight: 200; margin-top: 25px; max-width: 800px;">
|
||||
BuildPath isn't endorsed by Riot Games and doesn't reflect the views or opinions of
|
||||
Riot Games or anyone officially involved in producing or managing Riot Games properties.
|
||||
Riot Games, and all associated properties are trademarks or registered trademarks of Riot Games, Inc.
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: fit-content; margin: auto">
|
||||
<Logo />
|
||||
|
||||
<div style="margin-top: 20px">
|
||||
<h1>About</h1>
|
||||
<h3 style="margin-top: 20px">
|
||||
BuildPath: a tool for League of Legends champions runes and build paths.
|
||||
</h3>
|
||||
<h3 style="margin-top: 10px">Copyright (C) Valentin Haudiquet (@vhaudiquet)</h3>
|
||||
<h3 style="margin-top: 20px">Acknowledgments:</h3>
|
||||
<h3>- Sarah Emery, for the feedback on the designs and code</h3>
|
||||
<h3>- Martin Andrieux, for the nice algorithms :)</h3>
|
||||
<h3>- Paul Chaurand, for the feedback on the league data organization</h3>
|
||||
<h3>- Nathan Mérillon, for the tierlists ideas</h3>
|
||||
<h3>- Jean-Baptiste Döderlein, for the feedback on the mobile design</h3>
|
||||
<h3 style="margin-top: 20px">Libraries used:</h3>
|
||||
<h3>Vue.JS, Nuxt.JS, Chart.JS, svg-dom-arrows</h3>
|
||||
<h2 style="font-size: 1rem; font-weight: 200; margin-top: 25px; max-width: 800px">
|
||||
BuildPath isn't endorsed by Riot Games and doesn't reflect the views or opinions of Riot
|
||||
Games or anyone officially involved in producing or managing Riot Games properties. Riot
|
||||
Games, and all associated properties are trademarks or registered trademarks of Riot
|
||||
Games, Inc.
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.about-main-content {
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
display: flex;
|
||||
margin-top: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -2,99 +2,112 @@
|
||||
const route = useRoute()
|
||||
const championAlias = route.params.alias as string
|
||||
|
||||
const { data : championData } : {data : Ref<ChampionData>} = await useFetch("/api/champion/" + championAlias.toLowerCase())
|
||||
const { data: championData }: { data: Ref<ChampionData> } = await useFetch(
|
||||
'/api/champion/' + championAlias.toLowerCase()
|
||||
)
|
||||
const championId = championData.value.id
|
||||
|
||||
// Prefetch home page for faster navigation
|
||||
useHead({
|
||||
link: [
|
||||
{ rel: 'prefetch', href: '/' }
|
||||
]
|
||||
link: [{ rel: 'prefetch', href: '/' }]
|
||||
})
|
||||
|
||||
defineOgImageComponent('Champion', {
|
||||
title: championData.value.name,
|
||||
id: championId,
|
||||
winrate: championData.value.winrate,
|
||||
pickrate: championData.value.pickrate,
|
||||
gameCount: championData.value.gameCount,
|
||||
title: championData.value.name,
|
||||
id: championId,
|
||||
winrate: championData.value.winrate,
|
||||
pickrate: championData.value.pickrate,
|
||||
gameCount: championData.value.gameCount
|
||||
})
|
||||
useSeoMeta({
|
||||
title: championData.value.name,
|
||||
description: 'Build path and runes for ' + championData.value.name + ' on BuildPath'
|
||||
title: championData.value.name,
|
||||
description: 'Build path and runes for ' + championData.value.name + ' on BuildPath'
|
||||
})
|
||||
|
||||
const laneState = ref(0)
|
||||
const state = ref("runes")
|
||||
const state = ref('runes')
|
||||
const lane = ref(championData.value.lanes[laneState.value])
|
||||
function updateState(newState : string, newLane : number) {
|
||||
state.value = newState
|
||||
laneState.value = newLane
|
||||
lane.value = championData.value.lanes[laneState.value]
|
||||
function updateState(newState: string, newLane: number) {
|
||||
state.value = newState
|
||||
laneState.value = newLane
|
||||
lane.value = championData.value.lanes[laneState.value]
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>{{ championData.name }}</Title>
|
||||
</Head>
|
||||
<Head>
|
||||
<Title>{{ championData.name }}</Title>
|
||||
</Head>
|
||||
|
||||
<div id="alias-content-wrapper">
|
||||
|
||||
<NavBar :champion-name="championData.name"
|
||||
:champion-lanes="championData.lanes"
|
||||
@state-change="updateState"/>
|
||||
<div id="alias-content-wrapper">
|
||||
<NavBar
|
||||
:champion-name="championData.name"
|
||||
:champion-lanes="championData.lanes"
|
||||
@state-change="updateState"
|
||||
/>
|
||||
|
||||
<div id="champion-content">
|
||||
<ChampionTitle id="champion-title" v-if="championData.gameCount > 0"
|
||||
:champion-id="championId" :winrate="lane.winrate"
|
||||
:pickrate="lane.pickrate" :game-count="lane.count" />
|
||||
<RuneSelector v-if="state == 'runes' && championData.gameCount > 0"
|
||||
style="margin: auto; margin-top: 40px;"
|
||||
:runes="lane.runes!!" />
|
||||
<ItemViewer v-if="state == 'items' && championData.gameCount > 0"
|
||||
style="margin:auto; margin-top: 40px;"
|
||||
:builds="lane.builds!!" />
|
||||
<ItemTree v-if="state == 'alternatives' && championData.gameCount > 0"
|
||||
style="margin: auto; margin-top: 40px; width: fit-content;"
|
||||
:tree="lane.builds!!.tree" />
|
||||
<h2 v-if="championData.gameCount == 0"
|
||||
style="margin: auto; margin-top: 20px; width: fit-content;">
|
||||
Sorry, there is no data for this champion :(
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<ChampionTitle
|
||||
v-if="championData.gameCount > 0"
|
||||
id="champion-title"
|
||||
:champion-id="championId"
|
||||
:winrate="lane.winrate"
|
||||
:pickrate="lane.pickrate"
|
||||
:game-count="lane.count"
|
||||
/>
|
||||
<RuneSelector
|
||||
v-if="state == 'runes' && championData.gameCount > 0"
|
||||
style="margin: auto; margin-top: 40px"
|
||||
:runes="lane.runes!!"
|
||||
/>
|
||||
<ItemViewer
|
||||
v-if="state == 'items' && championData.gameCount > 0"
|
||||
style="margin: auto; margin-top: 40px"
|
||||
:builds="lane.builds!!"
|
||||
/>
|
||||
<ItemTree
|
||||
v-if="state == 'alternatives' && championData.gameCount > 0"
|
||||
style="margin: auto; margin-top: 40px; width: fit-content"
|
||||
:tree="lane.builds!!.tree"
|
||||
/>
|
||||
<h2
|
||||
v-if="championData.gameCount == 0"
|
||||
style="margin: auto; margin-top: 20px; width: fit-content"
|
||||
>
|
||||
Sorry, there is no data for this champion :(
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
#alias-content-wrapper {
|
||||
display: flex;
|
||||
/* min-height: 100vh; */
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
/* min-height: 100vh; */
|
||||
align-items: stretch;
|
||||
width: 100%;
|
||||
|
||||
overflow: hidden;
|
||||
overflow: hidden;
|
||||
}
|
||||
#champion-content {
|
||||
margin-top: 64px;
|
||||
margin-left: 39px;
|
||||
width: 100%;
|
||||
margin-top: 64px;
|
||||
margin-left: 39px;
|
||||
width: 100%;
|
||||
}
|
||||
@media only screen and (max-width: 650px) {
|
||||
#champion-content {
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
#champion-title {
|
||||
margin:auto;
|
||||
}
|
||||
#champion-content {
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
}
|
||||
#champion-title {
|
||||
margin: auto;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width: 1200px) {
|
||||
#alias-content-wrapper {
|
||||
flex-direction: column;
|
||||
padding-bottom: 120px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
#alias-content-wrapper {
|
||||
flex-direction: column;
|
||||
padding-bottom: 120px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,63 +1,60 @@
|
||||
<script setup lang="ts">
|
||||
import { POSITIONS, LANE_IMAGES, POSITIONS_STR } from '~/utils/cdragon';
|
||||
|
||||
import { POSITIONS, LANE_IMAGES, POSITIONS_STR } from '~/utils/cdragon'
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>Home</Title>
|
||||
</Head>
|
||||
<Head>
|
||||
<Title>Home</Title>
|
||||
</Head>
|
||||
|
||||
<div class="index-main-content">
|
||||
<div class="index-main-content">
|
||||
<NavBar :tierlist-list="true" />
|
||||
|
||||
<ChampionSelector class="index-champion-selector"/>
|
||||
|
||||
</div>
|
||||
<ChampionSelector class="index-champion-selector" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.index-main-content {
|
||||
display: flex;
|
||||
margin-top: 50px;
|
||||
display: flex;
|
||||
margin-top: 50px;
|
||||
}
|
||||
.index-champion-selector {
|
||||
width: 80%;
|
||||
width: 80%;
|
||||
}
|
||||
.index-tierlist-info-container {
|
||||
margin: auto;
|
||||
margin-top: 0px;
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
margin-top: 0px;
|
||||
width: fit-content;
|
||||
}
|
||||
#index-tierlists {
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
width: fit-content;
|
||||
margin: auto;
|
||||
margin-top: 10px;
|
||||
width: fit-content;
|
||||
}
|
||||
@media only screen and (max-width: 1240px) {
|
||||
.index-main-content {
|
||||
flex-direction: column;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.index-champion-selector {
|
||||
width: 100%;
|
||||
}
|
||||
.index-tierlist-info-container {
|
||||
display: flex;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
.index-main-content {
|
||||
flex-direction: column;
|
||||
margin-top: 5px;
|
||||
}
|
||||
.index-champion-selector {
|
||||
width: 100%;
|
||||
}
|
||||
.index-tierlist-info-container {
|
||||
display: flex;
|
||||
margin-bottom: 50px;
|
||||
}
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 500px) {
|
||||
#index-statp {
|
||||
display: none;
|
||||
}
|
||||
.index-tierlist-info-container {
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
#index-statp {
|
||||
display: none;
|
||||
}
|
||||
.index-tierlist-info-container {
|
||||
margin-bottom: 10px;
|
||||
margin-left: 10px;
|
||||
|
||||
display: none;
|
||||
}
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -1,105 +1,129 @@
|
||||
<script setup lang="ts">
|
||||
import { LANE_IMAGES, lanePositionToIndex, POSITIONS_STR } from '~/utils/cdragon';
|
||||
import { LANE_IMAGES, lanePositionToIndex, POSITIONS_STR } from '~/utils/cdragon'
|
||||
|
||||
const route = useRoute()
|
||||
const lane = route.params.lane as string
|
||||
|
||||
const {data: championsData} : ChampionsResponse = await useFetch(CDRAGON_BASE + "plugins/rcp-be-lol-game-data/global/default/v1/champion-summary.json")
|
||||
const { data: championsData }: ChampionsResponse = await useFetch(
|
||||
CDRAGON_BASE + 'plugins/rcp-be-lol-game-data/global/default/v1/champion-summary.json'
|
||||
)
|
||||
|
||||
const {data: championsLanes} : {data: Ref<Array<ChampionData>>} = await useFetch("/api/champions")
|
||||
const infoMap : Map<string, ChampionData> = new Map()
|
||||
for(let champion of championsLanes.value) {
|
||||
infoMap.set(champion.alias, champion)
|
||||
const { data: championsLanes }: { data: Ref<Array<ChampionData>> } =
|
||||
await useFetch('/api/champions')
|
||||
const infoMap: Map<string, ChampionData> = new Map()
|
||||
for (const champion of championsLanes.value) {
|
||||
infoMap.set(champion.alias, champion)
|
||||
}
|
||||
|
||||
const champions = championsData.value.slice(1).filter((champion) => {
|
||||
const championData : ChampionData | undefined = infoMap.get(champion.alias.toLowerCase())
|
||||
if(championData == undefined) return false;
|
||||
const champions = championsData.value.slice(1).filter(champion => {
|
||||
const championData: ChampionData | undefined = infoMap.get(champion.alias.toLowerCase())
|
||||
if (championData == undefined) return false
|
||||
|
||||
const lanes = championData.lanes
|
||||
return lanes.reduce((acc : boolean, current : {data:string, count:number}) =>
|
||||
acc || (current.data.toLowerCase() == lane.toLowerCase()), false)
|
||||
const lanes = championData.lanes
|
||||
return lanes.reduce(
|
||||
(acc: boolean, current: { data: string; count: number }) =>
|
||||
acc || current.data.toLowerCase() == lane.toLowerCase(),
|
||||
false
|
||||
)
|
||||
})
|
||||
|
||||
const allChampions = champions.map((x) => {
|
||||
const championData : ChampionData = infoMap.get(x.alias.toLowerCase())!!
|
||||
const allChampions = champions
|
||||
.map(x => {
|
||||
const championData: ChampionData = infoMap.get(x.alias.toLowerCase())!
|
||||
|
||||
let currentLane = championData.lanes[0]
|
||||
for(let championLane of championData.lanes) {
|
||||
if(championLane.data.toLowerCase() == lane.toLowerCase()) {
|
||||
currentLane = championLane
|
||||
break
|
||||
}
|
||||
for (const championLane of championData.lanes) {
|
||||
if (championLane.data.toLowerCase() == lane.toLowerCase()) {
|
||||
currentLane = championLane
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return {lane: currentLane, champion: x}
|
||||
}).sort((a, b) => b.lane.pickrate - a.lane.pickrate)
|
||||
return { lane: currentLane, champion: x }
|
||||
})
|
||||
.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))
|
||||
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.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
|
||||
})
|
||||
return (
|
||||
allChampions as Array<{ lane: LaneData; champion: Champion; scaledPickrate: number }>
|
||||
).filter(({ scaledPickrate: scaledPickrate }) => {
|
||||
return scaledPickrate > min && scaledPickrate <= max
|
||||
})
|
||||
}
|
||||
|
||||
const tiers: Array<{title:string, data: Array<{lane: LaneData, champion: Champion}>}> = []
|
||||
tiers.push({title: "S", data: tierFromScaledPickrate(0.9, 1)})
|
||||
tiers.push({title: "A", data: tierFromScaledPickrate(0.7, 0.9)})
|
||||
tiers.push({title: "B", data: tierFromScaledPickrate(0.5, 0.7)})
|
||||
tiers.push({title: "C", data: tierFromScaledPickrate(0.3, 0.5)})
|
||||
tiers.push({title: "D", data: tierFromScaledPickrate(0.1, 0.3)})
|
||||
tiers.push({title: "F", data: tierFromScaledPickrate(0, 0.1)})
|
||||
const tiers: Array<{ title: string; data: Array<{ lane: LaneData; champion: Champion }> }> = []
|
||||
tiers.push({ title: 'S', data: tierFromScaledPickrate(0.9, 1) })
|
||||
tiers.push({ title: 'A', data: tierFromScaledPickrate(0.7, 0.9) })
|
||||
tiers.push({ title: 'B', data: tierFromScaledPickrate(0.5, 0.7) })
|
||||
tiers.push({ title: 'C', data: tierFromScaledPickrate(0.3, 0.5) })
|
||||
tiers.push({ title: 'D', data: tierFromScaledPickrate(0.1, 0.3) })
|
||||
tiers.push({ title: 'F', data: tierFromScaledPickrate(0, 0.1) })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Head>
|
||||
<Title>Tierlist for {{ POSITIONS_STR[lanePositionToIndex(lane)] }}</Title>
|
||||
</Head>
|
||||
<Head>
|
||||
<Title>Tierlist for {{ POSITIONS_STR[lanePositionToIndex(lane)] }}</Title>
|
||||
</Head>
|
||||
|
||||
<div style="display: flex; min-height: 100vh; align-items: stretch; width: 100%;">
|
||||
<NavBar :tierlist-list="true" />
|
||||
<div style="display: flex; min-height: 100vh; align-items: stretch; width: 100%">
|
||||
<NavBar :tierlist-list="true" />
|
||||
|
||||
<div id="tierlist-container" style="margin-left: 10px; width: 100%; overflow-y: scroll;">
|
||||
<div id="tierlist-container" style="margin-left: 10px; width: 100%; overflow-y: scroll">
|
||||
<div
|
||||
style="
|
||||
margin-left: 0px;
|
||||
margin-top: 20px;
|
||||
display: flex;
|
||||
margin-bottom: 30px;
|
||||
align-items: center;
|
||||
"
|
||||
>
|
||||
<h1 style="margin-left: 10px; font-size: 2.8rem; font-weight: 300">Tierlist for</h1>
|
||||
<NuxtImg
|
||||
format="webp"
|
||||
style="margin-left: 10px"
|
||||
width="50"
|
||||
height="50"
|
||||
:src="LANE_IMAGES[lanePositionToIndex(lane)]"
|
||||
/>
|
||||
<h1 style="margin-left: 10px; font-size: 2.8rem; font-weight: 300">
|
||||
{{ POSITIONS_STR[lanePositionToIndex(lane)] }}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
<div style="margin-left: 0px; margin-top: 20px; display: flex; margin-bottom: 30px; align-items: center">
|
||||
<h1 style="margin-left: 10px; font-size: 2.8rem; font-weight: 300;">Tierlist for</h1>
|
||||
<NuxtImg format="webp" style="margin-left: 10px;"
|
||||
width="50" height="50"
|
||||
:src="LANE_IMAGES[lanePositionToIndex(lane)]" />
|
||||
<h1 style="margin-left: 10px; font-size: 2.8rem; font-weight: 300;">{{ POSITIONS_STR[lanePositionToIndex(lane)] }}</h1>
|
||||
</div>
|
||||
<TierlistTier v-for="tier in tiers" :title="tier.title" :tier="tier.data" />
|
||||
|
||||
<TierlistTier v-for="tier in tiers" :title="tier.title" :tier="tier.data" />
|
||||
|
||||
<TierlistChart id="chart" :data="tiers" />
|
||||
|
||||
</div>
|
||||
<TierlistChart id="chart" :data="tiers" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
#chart {
|
||||
margin-left: 100px;
|
||||
margin-right: 100px;
|
||||
margin-bottom: 100px;
|
||||
margin-top: 40px
|
||||
margin-left: 100px;
|
||||
margin-right: 100px;
|
||||
margin-bottom: 100px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 450px) {
|
||||
#chart {
|
||||
margin-left: 2px;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
#tierlist-container {
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
#chart {
|
||||
margin-left: 2px;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 40px;
|
||||
margin-top: 40px;
|
||||
}
|
||||
#tierlist-container {
|
||||
padding-bottom: 120px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user