Big champion stats optim :)
This commit is contained in:
@@ -6,6 +6,7 @@ function sameArrays(array1 : Array<any>, array2 : Array<any>) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
import { MongoClient } from "mongodb";
|
||||||
import { ItemTree, treeInit, treeMerge, treeCutBranches, treeSort } from "./item_tree";
|
import { ItemTree, treeInit, treeMerge, treeCutBranches, treeSort } from "./item_tree";
|
||||||
const itemDict = new Map()
|
const itemDict = new Map()
|
||||||
|
|
||||||
@@ -57,6 +58,12 @@ type LaneData = {
|
|||||||
runes: Array<Rune>
|
runes: Array<Rune>
|
||||||
builds: Builds
|
builds: Builds
|
||||||
}
|
}
|
||||||
|
type ChampionData = {
|
||||||
|
champion: Champion
|
||||||
|
winningMatches: number
|
||||||
|
losingMatches: number
|
||||||
|
lanes: Array<LaneData>
|
||||||
|
}
|
||||||
|
|
||||||
function handleParticipantRunes(participant, runes: Array<Rune>) {
|
function handleParticipantRunes(participant, runes: Array<Rune>) {
|
||||||
const primaryStyle = participant.perks.styles[0].style
|
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) {
|
function handleMatch(match: any, champions : Map<number, ChampionData>) {
|
||||||
const championId = champion.id
|
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 database = client.db("matches");
|
||||||
const matches = database.collection(patch)
|
const matches = database.collection(patch)
|
||||||
const allMatches = matches.find()
|
const allMatches = matches.find()
|
||||||
|
const totalMatches: number = await matches.countDocuments()
|
||||||
|
|
||||||
let winningMatches = 0;
|
let currentMatch = 0;
|
||||||
let losingMatches = 0;
|
|
||||||
let totalMatches = 0;
|
|
||||||
const lanes : Array<LaneData> = [];
|
|
||||||
for await (let match of allMatches) {
|
for await (let match of allMatches) {
|
||||||
totalMatches += 1;
|
console.log("Computing champion stats, game entry " + currentMatch + "/" + totalMatches + " ...")
|
||||||
let participantIndex = 0;
|
currentMatch += 1;
|
||||||
for(let participant of match.info.participants) {
|
handleMatch(match, champions)
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let totalChampionMatches = winningMatches + losingMatches;
|
return totalMatches
|
||||||
|
}
|
||||||
|
|
||||||
arrayRemovePercentage(lanes, totalChampionMatches, 0.2)
|
async function finalizeChampionStats(champion: ChampionData, totalMatches: number) {
|
||||||
lanes.sort((a, b) => b.count - a.count)
|
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
|
// Filter runes to keep 3 most played
|
||||||
for(let lane of lanes) {
|
for(let lane of champion.lanes) {
|
||||||
const runes = lane.runes
|
const runes = lane.runes
|
||||||
|
|
||||||
runes.sort((a, b) => b.count - a.count)
|
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;
|
rune.pickrate = rune.count / lane.count;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(let lane of lanes) {
|
for(let lane of champion.lanes) {
|
||||||
const builds = lane.builds
|
const builds = lane.builds
|
||||||
|
|
||||||
// Cut item tree branches to keep only 4 branches every time and with percentage threshold
|
// 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)
|
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.winrate = lane.winningMatches / lane.count
|
||||||
lane.pickrate = lane.count / totalMatches
|
lane.pickrate = lane.count / totalMatches
|
||||||
}
|
}
|
||||||
|
|
||||||
return {name: champion.name,
|
return {name: champion.champion.name,
|
||||||
alias: champion.alias.toLowerCase(),
|
alias: champion.champion.alias.toLowerCase(),
|
||||||
id: championId,
|
id: champion.champion.id,
|
||||||
lanes: lanes,
|
lanes: champion.lanes,
|
||||||
winrate: winningMatches / totalChampionMatches,
|
winrate: champion.winningMatches / totalChampionMatches,
|
||||||
gameCount: totalChampionMatches,
|
gameCount: totalChampionMatches,
|
||||||
pickrate: totalChampionMatches/totalMatches,
|
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() {
|
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 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()
|
const list = await response.json()
|
||||||
return list.slice(1)
|
return list.slice(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function makeChampionsStats(client, patch : number) {
|
async function makeChampionsStats(client: MongoClient, patch : string) {
|
||||||
var globalItems = await itemList()
|
var globalItems = await itemList()
|
||||||
for(let item of globalItems) {
|
for(let item of globalItems) {
|
||||||
itemDict.set(item.id, item)
|
itemDict.set(item.id, item)
|
||||||
@@ -293,15 +297,30 @@ async function makeChampionsStats(client, patch : number) {
|
|||||||
|
|
||||||
const list = await championList()
|
const list = await championList()
|
||||||
console.log("Generating stats for " + list.length + " champions")
|
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) {
|
for(let champion of list) {
|
||||||
console.log("Entry " + i + "/" + list.length + " (" + champion.name + ")...")
|
champions.set(champion.id, {
|
||||||
await makeChampionStat(client, patch, champion)
|
champion: {id: champion.id, name: champion.name, alias: champion.alias},
|
||||||
i += 1
|
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 database = client.db("champions")
|
||||||
const collection = database.collection(patch)
|
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})
|
await collection.createIndex({alias:1})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user