So much space and nothing to say
Hello.
// Use rendezvous hashing to place players // in an even (or weighted) number of pools // https://en.wikipedia.org/wiki/Rendezvous_hashing // https://highscalability.com/consistent-hashing-algorithm/ // https://github.com/Munawwar/hrw-hash // https://pypi.org/project/mmh3/ import murmurhash from 'murmurhash'; function hashToUnitInterval(s: string): number { return (murmurhash.v3(s) + 1) / 2**32 } class Pool { name: string; weight: number; computeWeightedScore(key: string) { const score = hashToUnitInterval(`${this.name}: ${key}`); const log_score = 1.0 / -Math.log(score); return this.weight * log_score; } constructor(name: string, weight: number) { this.name = name; this.weight = weight; } } function determinePool(pools: Pool[], key: string) { return pools.sort((pool1, pool2) => pool1.computeWeightedScore(key) > pool2.computeWeightedScore(key) ? 1 : pool1.computeWeightedScore(key) === pool2.computeWeightedScore(key) ? 0 : -1 )[pools.length - 1]; } const threePools = [ new Pool('pool1', 10), new Pool('pool2', 10), new Pool('pool3', 10) ]; const threeWeightedPools = [ new Pool('pool1', 100), new Pool('pool2', 50), new Pool('pool3', 5) ]; const sixPools = [ new Pool('pool1', 100), new Pool('pool2', 100), new Pool('pool3', 100), new Pool('pool4', 100), new Pool('pool5', 100), new Pool('pool6', 100), ] const players = Array.from((new Array(10000)).keys()); const threePoolsCounts: Record= { pool1: 0, pool2: 0, pool3: 0 }; const threePoolsPlayers = players .map((player) => determinePool(threePools, player.toString())); threePoolsPlayers.forEach(player => threePoolsCounts[player.name] += 1); const threeWeightedPoolsCounts: Record = { pool1: 0, pool2: 0, pool3: 0 }; const threeWeightedPoolsPlayers = players .map((player) => determinePool(threeWeightedPools, player.toString())); threeWeightedPoolsPlayers.forEach(player => threeWeightedPoolsCounts[player.name] += 1); const sixPoolsCounts: Record = { pool1: 0, pool2: 0, pool3: 0, pool4: 0, pool5: 0, pool6: 0 }; const sixPoolsPlayers = players.map((player) => determinePool(sixPools, player.toString())) sixPoolsPlayers.forEach(player => sixPoolsCounts[player.name] += 1); console.log('three evenly weighted pools:', threePoolsCounts); console.log('three weighted pools: ', threeWeightedPoolsCounts); console.log('six evenly weighted pools: ', sixPoolsCounts);