refactor/match_collector: refactor platform handling logic

This commit is contained in:
2026-04-23 18:08:17 +02:00
parent a5728a147f
commit 360be86c10
4 changed files with 140 additions and 83 deletions

View File

@@ -11,6 +11,7 @@ import {
areTreeSimilars, areTreeSimilars,
treeDeriveTags treeDeriveTags
} from './item_tree' } from './item_tree'
import { PLATFORM_KEYS } from './platform'
import { Match, Timeline, Participant, Frame } from './api' import { Match, Timeline, Participant, Frame } from './api'
@@ -345,10 +346,10 @@ function handleMatch(match: Match, champions: Map<number, ChampionData>, platfor
// Track region distribution for this lane // Track region distribution for this lane
if (lane.regionDistribution && platform) { if (lane.regionDistribution && platform) {
const platformKey = platform.toLowerCase() const platformKey = platform.toLowerCase()
if (platformKey === 'euw1') lane.regionDistribution.euw++ const regionKey = PLATFORM_KEYS[platformKey]
else if (platformKey === 'eun1') lane.regionDistribution.eun++ if (regionKey) {
else if (platformKey === 'na1') lane.regionDistribution.na++ lane.regionDistribution[regionKey]!++
else if (platformKey === 'kr') lane.regionDistribution.kr++ }
} }
// Initialize matchups if not present // Initialize matchups if not present

View File

@@ -5,22 +5,7 @@ import { MongoClient } from 'mongodb'
import champion_stat from './champion_stat' import champion_stat from './champion_stat'
import { Match } from './api' import { Match } from './api'
import { PLATFORMS, getPlatformBaseUrl, getRegionalBaseUrl, getRegionForPlatform } from './platform'
// Region configuration: platform -> regional routing value
const PLATFORMS: Record<string, string> = {
EUW1: 'EUROPE',
EUN1: 'EUROPE',
NA1: 'AMERICAS',
KR: 'ASIA'
}
function getPlatformBaseUrl(platform: string): string {
return `https://${platform.toLowerCase()}.api.riotgames.com`
}
function getRegionalBaseUrl(region: string): string {
return `https://${region.toLowerCase()}.api.riotgames.com`
}
main() main()
@@ -75,7 +60,7 @@ async function main() {
// Determine region from matchId (format: PLATFORM_matchId) // Determine region from matchId (format: PLATFORM_matchId)
// Map platform prefix to regional routing value for match API // Map platform prefix to regional routing value for match API
const matchPlatformPrefix = game.split('_')[0] const matchPlatformPrefix = game.split('_')[0]
const matchRegion = PLATFORMS[matchPlatformPrefix] || region const matchRegion = getRegionForPlatform(matchPlatformPrefix) || region
const gameMatch = await match(game, matchRegion) const gameMatch = await match(game, matchRegion)
const gameTimeline = await matchTimeline(game, matchRegion) const gameTimeline = await matchTimeline(game, matchRegion)
gameMatch.timeline = gameTimeline gameMatch.timeline = gameTimeline

View File

@@ -1,11 +1,12 @@
type GoldAdvantageTag = 'ahead' | 'behind' | 'even' import {
PlatformCounts,
REGION_KEYS,
initPlatformCounts,
mergePlatformCounts,
singlePlatformCount
} from './platform'
type PlatformCounts = { type GoldAdvantageTag = 'ahead' | 'behind' | 'even'
euw: number
eun: number
na: number
kr: number
}
// Item tags that can be derived from purchase patterns // Item tags that can be derived from purchase patterns
type ItemTag = 'ahead' | 'behind' | 'region_euw' | 'region_eun' | 'region_na' | 'region_kr' type ItemTag = 'ahead' | 'behind' | 'region_euw' | 'region_eun' | 'region_na' | 'region_kr'
@@ -30,10 +31,6 @@ type ItemTree = {
tags: Array<ItemTag> tags: Array<ItemTag>
} }
function initPlatformCounts(): PlatformCounts {
return { euw: 0, eun: 0, na: 0, kr: 0 }
}
function treeInit(): ItemTree { function treeInit(): ItemTree {
return { return {
data: undefined, data: undefined,
@@ -63,10 +60,7 @@ function nodeMerge(itemtree: ItemTree, node: ItemTree) {
child.boughtWhen.behindCount += node.boughtWhen.behindCount child.boughtWhen.behindCount += node.boughtWhen.behindCount
// Merge platform counts // Merge platform counts
child.platformCount.euw += node.platformCount.euw mergePlatformCounts(child.platformCount, node.platformCount)
child.platformCount.eun += node.platformCount.eun
child.platformCount.na += node.platformCount.na
child.platformCount.kr += node.platformCount.kr
next = child next = child
break break
@@ -99,7 +93,6 @@ function treeMerge(
let current = itemtree let current = itemtree
for (const item of items) { for (const item of items) {
const platformKey = item.platform ? item.platform.toLowerCase() : null
current = nodeMerge(current, { current = nodeMerge(current, {
data: item.itemId, data: item.itemId,
count: 1, count: 1,
@@ -110,12 +103,7 @@ function treeMerge(
meanGold: 0 meanGold: 0
}, },
children: [], children: [],
platformCount: { platformCount: item.platform ? singlePlatformCount(item.platform) : initPlatformCounts(),
euw: platformKey === 'euw1' ? 1 : 0,
eun: platformKey === 'eun1' ? 1 : 0,
na: platformKey === 'na1' ? 1 : 0,
kr: platformKey === 'kr' ? 1 : 0
},
tags: [] tags: []
}) })
} }
@@ -174,12 +162,7 @@ function treeClone(tree: ItemTree): ItemTree {
evenCount: tree.boughtWhen.evenCount, evenCount: tree.boughtWhen.evenCount,
meanGold: tree.boughtWhen.meanGold meanGold: tree.boughtWhen.meanGold
}, },
platformCount: { platformCount: { ...tree.platformCount },
euw: tree.platformCount.euw,
eun: tree.platformCount.eun,
na: tree.platformCount.na,
kr: tree.platformCount.kr
},
tags: [...tree.tags] tags: [...tree.tags]
} }
} }
@@ -192,10 +175,7 @@ function treeMergeTree(t1: ItemTree, t2: ItemTree): ItemTree {
t1.count += t2.count t1.count += t2.count
// Merge platform counts // Merge platform counts
t1.platformCount.euw += t2.platformCount.euw mergePlatformCounts(t1.platformCount, t2.platformCount)
t1.platformCount.eun += t2.platformCount.eun
t1.platformCount.na += t2.platformCount.na
t1.platformCount.kr += t2.platformCount.kr
// Merge boughtWhen // Merge boughtWhen
t1.boughtWhen.aheadCount += t2.boughtWhen.aheadCount t1.boughtWhen.aheadCount += t2.boughtWhen.aheadCount
@@ -302,44 +282,31 @@ function deriveTags(node: ItemTree, expectedRegionDistribution?: PlatformCounts)
} }
// Derive region tags by comparing against expected distribution // Derive region tags by comparing against expected distribution
const totalRegionCount = const totalRegionCount = REGION_KEYS.reduce((sum, key) => sum + node.platformCount[key], 0)
node.platformCount.euw + node.platformCount.eun + node.platformCount.na + node.platformCount.kr
if (totalRegionCount > 0 && expectedRegionDistribution) { if (totalRegionCount > 0 && expectedRegionDistribution) {
const totalExpected = const totalExpected = REGION_KEYS.reduce((sum, key) => sum + expectedRegionDistribution[key], 0)
expectedRegionDistribution.euw +
expectedRegionDistribution.eun +
expectedRegionDistribution.na +
expectedRegionDistribution.kr
if (totalExpected > 0) { if (totalExpected > 0) {
// Calculate expected percentages
const expectedEuwPct = expectedRegionDistribution.euw / totalExpected
const expectedEunPct = expectedRegionDistribution.eun / totalExpected
const expectedNaPct = expectedRegionDistribution.na / totalExpected
const expectedKrPct = expectedRegionDistribution.kr / totalExpected
// Calculate actual percentages for this item
const actualEuwPct = node.platformCount.euw / totalRegionCount
const actualEunPct = node.platformCount.eun / totalRegionCount
const actualNaPct = node.platformCount.na / totalRegionCount
const actualKrPct = node.platformCount.kr / totalRegionCount
// Tag if the item is significantly more popular in a region (>= 1.5x expected rate) // Tag if the item is significantly more popular in a region (>= 1.5x expected rate)
// and has a minimum absolute percentage (>= 10%) // and has a minimum absolute percentage (>= 10%)
const SIGNIFICANCE_THRESHOLD = 1.5 const SIGNIFICANCE_THRESHOLD = 1.5
const MINIMUM_PCT = 0.1 const MINIMUM_PCT = 0.1
if (actualEuwPct >= expectedEuwPct * SIGNIFICANCE_THRESHOLD && actualEuwPct >= MINIMUM_PCT) { // Loop through all regions to derive tags
tags.push('region_euw') const regionTags: Array<{ key: keyof PlatformCounts; tag: ItemTag }> = [
} { key: 'euw', tag: 'region_euw' },
if (actualEunPct >= expectedEunPct * SIGNIFICANCE_THRESHOLD && actualEunPct >= MINIMUM_PCT) { { key: 'eun', tag: 'region_eun' },
tags.push('region_eun') { key: 'na', tag: 'region_na' },
} { key: 'kr', tag: 'region_kr' }
if (actualNaPct >= expectedNaPct * SIGNIFICANCE_THRESHOLD && actualNaPct >= MINIMUM_PCT) { ]
tags.push('region_na')
} for (const { key, tag } of regionTags) {
if (actualKrPct >= expectedKrPct * SIGNIFICANCE_THRESHOLD && actualKrPct >= MINIMUM_PCT) { const expectedPct = expectedRegionDistribution[key] / totalExpected
tags.push('region_kr') const actualPct = node.platformCount[key] / totalRegionCount
if (actualPct >= expectedPct * SIGNIFICANCE_THRESHOLD && actualPct >= MINIMUM_PCT) {
tags.push(tag)
}
} }
} }
} }

104
match_collector/platform.ts Normal file
View File

@@ -0,0 +1,104 @@
/**
* Platform and region configuration for Riot Games API
*
* Platforms are the server clusters (EUW1, EUN1, NA1, KR)
* Regions are the routing values for match API (EUROPE, AMERICAS, ASIA)
*/
// Platform to regional routing value mapping
const PLATFORMS: Record<string, string> = {
EUW1: 'EUROPE',
EUN1: 'EUROPE',
NA1: 'AMERICAS',
KR: 'ASIA'
}
// Platform counts for tracking item purchases per region
type PlatformCounts = {
euw: number
eun: number
na: number
kr: number
}
// Platform key mapping for converting platform strings to PlatformCounts keys
const PLATFORM_KEYS: Record<string, keyof PlatformCounts> = {
euw1: 'euw',
eun1: 'eun',
na1: 'na',
kr: 'kr'
}
// List of all region keys for iteration
const REGION_KEYS: Array<keyof PlatformCounts> = ['euw', 'eun', 'na', 'kr']
/**
* Get the base URL for platform-specific API calls (e.g., league-v4)
*/
function getPlatformBaseUrl(platform: string): string {
return `https://${platform.toLowerCase()}.api.riotgames.com`
}
/**
* Get the base URL for regional API calls (e.g., match-v5)
*/
function getRegionalBaseUrl(region: string): string {
return `https://${region.toLowerCase()}.api.riotgames.com`
}
/**
* Get the regional routing value for a platform
* Falls back to the provided default region if platform not found
*/
function getRegionForPlatform(platform: string): string | undefined {
return PLATFORMS[platform]
}
/**
* Initialize an empty PlatformCounts object
*/
function initPlatformCounts(): PlatformCounts {
return { euw: 0, eun: 0, na: 0, kr: 0 }
}
/**
* Merge platform counts from source into target
*/
function mergePlatformCounts(target: PlatformCounts, source: PlatformCounts): void {
for (const key of REGION_KEYS) {
target[key] += source[key]
}
}
/**
* Create a platform count with a single platform set to 1
*/
function singlePlatformCount(platform: string): PlatformCounts {
const counts = initPlatformCounts()
const key = PLATFORM_KEYS[platform.toLowerCase()]
if (key) {
counts[key] = 1
}
return counts
}
/**
* Get the PlatformCounts key for a platform string
*/
function getPlatformKey(platform: string): keyof PlatformCounts | undefined {
return PLATFORM_KEYS[platform.toLowerCase()]
}
export {
PLATFORMS,
PlatformCounts,
PLATFORM_KEYS,
REGION_KEYS,
getPlatformBaseUrl,
getRegionalBaseUrl,
getRegionForPlatform,
initPlatformCounts,
mergePlatformCounts,
singlePlatformCount,
getPlatformKey
}