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);