Big champion stats optim :)
This commit is contained in:
@@ -6,6 +6,7 @@ function sameArrays(array1 : Array<any>, array2 : Array<any>) {
|
||||
return true;
|
||||
}
|
||||
|
||||
import { MongoClient } from "mongodb";
|
||||
import { ItemTree, treeInit, treeMerge, treeCutBranches, treeSort } from "./item_tree";
|
||||
const itemDict = new Map()
|
||||
|
||||
@@ -57,6 +58,12 @@ type LaneData = {
|
||||
runes: Array<Rune>
|
||||
builds: Builds
|
||||
}
|
||||
type ChampionData = {
|
||||
champion: Champion
|
||||
winningMatches: number
|
||||
losingMatches: number
|
||||
lanes: Array<LaneData>
|
||||
}
|
||||
|
||||
function handleParticipantRunes(participant, runes: Array<Rune>) {
|
||||
const primaryStyle = participant.perks.styles[0].style
|
||||
@@ -161,60 +168,64 @@ function handleMatchItems(timeline, participant: any, participantIndex : number,
|
||||
}
|
||||
}
|
||||
|
||||
async function championInfos(client, patch: number, champion: Champion) {
|
||||
const championId = champion.id
|
||||
function handleMatch(match: any, champions : Map<number, ChampionData>) {
|
||||
let participantIndex = 0;
|
||||
for(let participant of match.info.participants) {
|
||||
participantIndex += 1
|
||||
const championId = participant.championId
|
||||
const champion = champions.get(championId)
|
||||
|
||||
// Lanes
|
||||
let lane = champion.lanes.find((x) => x.data == participant.teamPosition)
|
||||
if(lane == undefined) {
|
||||
const builds : Builds = {tree:treeInit(), start: [], bootsFirst: 0, boots: [], lateGame: [], suppItems: []}
|
||||
lane = {count:1, data: participant.teamPosition, runes:[], builds:builds, winningMatches: 0, losingMatches: 0, winrate: 0, pickrate: 0}
|
||||
champion.lanes.push(lane)
|
||||
}
|
||||
else lane.count += 1
|
||||
|
||||
// Winrate
|
||||
if(participant.win) {
|
||||
champion.winningMatches++;
|
||||
lane.winningMatches++;
|
||||
}
|
||||
else {
|
||||
champion.losingMatches++;
|
||||
lane.losingMatches++;
|
||||
}
|
||||
|
||||
// Runes
|
||||
handleParticipantRunes(participant, lane.runes)
|
||||
|
||||
// Items
|
||||
handleMatchItems(match.timeline, participant, participantIndex, lane.builds)
|
||||
}
|
||||
}
|
||||
|
||||
async function handleMatchList(client: MongoClient, patch: string, champions: Map<number, ChampionData>) {
|
||||
const database = client.db("matches");
|
||||
const matches = database.collection(patch)
|
||||
const allMatches = matches.find()
|
||||
const totalMatches: number = await matches.countDocuments()
|
||||
|
||||
let winningMatches = 0;
|
||||
let losingMatches = 0;
|
||||
let totalMatches = 0;
|
||||
const lanes : Array<LaneData> = [];
|
||||
let currentMatch = 0;
|
||||
for await (let match of allMatches) {
|
||||
totalMatches += 1;
|
||||
let participantIndex = 0;
|
||||
for(let participant of match.info.participants) {
|
||||
participantIndex += 1
|
||||
if(participant.championId != championId) continue;
|
||||
|
||||
// Winrate
|
||||
if(participant.win)
|
||||
winningMatches += 1;
|
||||
else
|
||||
losingMatches += 1;
|
||||
|
||||
// Lanes
|
||||
let lane = lanes.find((x) => x.data == participant.teamPosition)
|
||||
if(lane == undefined) {
|
||||
const builds : Builds = {tree:treeInit(), start: [], bootsFirst: 0, boots: [], lateGame: [], suppItems: []}
|
||||
lane = {count:1, data: participant.teamPosition, runes:[], builds:builds, winningMatches: 0, losingMatches: 0, winrate: 0, pickrate: 0}
|
||||
lanes.push(lane)
|
||||
}
|
||||
else lane.count += 1
|
||||
|
||||
if(participant.win)
|
||||
lane.winningMatches += 1;
|
||||
else
|
||||
lane.losingMatches += 1;
|
||||
|
||||
// Runes
|
||||
handleParticipantRunes(participant, lane.runes)
|
||||
|
||||
// Items
|
||||
handleMatchItems(match.timeline, participant, participantIndex, lane.builds)
|
||||
|
||||
break;
|
||||
}
|
||||
console.log("Computing champion stats, game entry " + currentMatch + "/" + totalMatches + " ...")
|
||||
currentMatch += 1;
|
||||
handleMatch(match, champions)
|
||||
}
|
||||
|
||||
let totalChampionMatches = winningMatches + losingMatches;
|
||||
return totalMatches
|
||||
}
|
||||
|
||||
arrayRemovePercentage(lanes, totalChampionMatches, 0.2)
|
||||
lanes.sort((a, b) => b.count - a.count)
|
||||
async function finalizeChampionStats(champion: ChampionData, totalMatches: number) {
|
||||
let totalChampionMatches = champion.winningMatches + champion.losingMatches;
|
||||
|
||||
arrayRemovePercentage(champion.lanes, totalChampionMatches, 0.2)
|
||||
champion.lanes.sort((a, b) => b.count - a.count)
|
||||
|
||||
// Filter runes to keep 3 most played
|
||||
for(let lane of lanes) {
|
||||
for(let lane of champion.lanes) {
|
||||
const runes = lane.runes
|
||||
|
||||
runes.sort((a, b) => b.count - a.count)
|
||||
@@ -225,7 +236,7 @@ async function championInfos(client, patch: number, champion: Champion) {
|
||||
rune.pickrate = rune.count / lane.count;
|
||||
}
|
||||
|
||||
for(let lane of lanes) {
|
||||
for(let lane of champion.lanes) {
|
||||
const builds = lane.builds
|
||||
|
||||
// Cut item tree branches to keep only 4 branches every time and with percentage threshold
|
||||
@@ -257,35 +268,28 @@ async function championInfos(client, patch: number, champion: Champion) {
|
||||
builds.lateGame.sort((a, b) => b.count - a.count)
|
||||
}
|
||||
|
||||
for(let lane of lanes) {
|
||||
for(let lane of champion.lanes) {
|
||||
lane.winrate = lane.winningMatches / lane.count
|
||||
lane.pickrate = lane.count / totalMatches
|
||||
}
|
||||
|
||||
return {name: champion.name,
|
||||
alias: champion.alias.toLowerCase(),
|
||||
id: championId,
|
||||
lanes: lanes,
|
||||
winrate: winningMatches / totalChampionMatches,
|
||||
return {name: champion.champion.name,
|
||||
alias: champion.champion.alias.toLowerCase(),
|
||||
id: champion.champion.id,
|
||||
lanes: champion.lanes,
|
||||
winrate: champion.winningMatches / totalChampionMatches,
|
||||
gameCount: totalChampionMatches,
|
||||
pickrate: totalChampionMatches/totalMatches,
|
||||
};
|
||||
}
|
||||
|
||||
async function makeChampionStat(client, patch : number, champion : Champion) {
|
||||
const championInfo = await championInfos(client, patch, champion)
|
||||
const database = client.db("champions")
|
||||
const collection = database.collection(patch)
|
||||
await collection.updateOne({id: championInfo.id}, {$set: championInfo}, { upsert: true })
|
||||
}
|
||||
|
||||
async function championList() {
|
||||
const response = await fetch("https://raw.communitydragon.org/latest/plugins/rcp-be-lol-game-data/global/default/v1/champion-summary.json");
|
||||
const list = await response.json()
|
||||
return list.slice(1)
|
||||
}
|
||||
|
||||
async function makeChampionsStats(client, patch : number) {
|
||||
async function makeChampionsStats(client: MongoClient, patch : string) {
|
||||
var globalItems = await itemList()
|
||||
for(let item of globalItems) {
|
||||
itemDict.set(item.id, item)
|
||||
@@ -293,15 +297,30 @@ async function makeChampionsStats(client, patch : number) {
|
||||
|
||||
const list = await championList()
|
||||
console.log("Generating stats for " + list.length + " champions")
|
||||
let i = 0;
|
||||
|
||||
// Pre-generate list of champions
|
||||
const champions: Map<number, ChampionData> = new Map()
|
||||
for(let champion of list) {
|
||||
console.log("Entry " + i + "/" + list.length + " (" + champion.name + ")...")
|
||||
await makeChampionStat(client, patch, champion)
|
||||
i += 1
|
||||
champions.set(champion.id, {
|
||||
champion: {id: champion.id, name: champion.name, alias: champion.alias},
|
||||
winningMatches: 0,
|
||||
losingMatches: 0,
|
||||
lanes: []
|
||||
})
|
||||
}
|
||||
|
||||
// Loop through all matches to generate stats
|
||||
const totalMatches = await handleMatchList(client, patch, champions)
|
||||
|
||||
// Finalize and save stats for every champion
|
||||
const database = client.db("champions")
|
||||
const collection = database.collection(patch)
|
||||
for(let champion of list) {
|
||||
const championInfo = await finalizeChampionStats(champions.get(champion.id), totalMatches)
|
||||
await collection.updateOne({id: champion.id}, {$set: championInfo}, { upsert: true })
|
||||
}
|
||||
|
||||
// Create alias-index for better key-find
|
||||
await collection.createIndex({alias:1})
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user