Smooth Weighted Round-Robin Balancer
Distribute selections across weighted nodes with the smooth weighted round-robin algorithm, keeping interleaving fair without randomness.
Code
interface WeightedNode<T> {
value: T;
weight: number;
current: number;
}
export class SmoothWeightedRoundRobin<T> {
private readonly nodes: WeightedNode<T>[] = [];
private totalWeight = 0;
add(value: T, weight: number): this {
if (!Number.isInteger(weight) || weight < 1) {
throw new RangeError("weight must be a positive integer");
}
this.nodes.push({ value, weight, current: 0 });
this.totalWeight += weight;
return this;
}
remove(value: T): boolean {
const index = this.nodes.findIndex((node) => Object.is(node.value, value));
if (index === -1) return false;
this.totalWeight -= this.nodes[index].weight;
this.nodes.splice(index, 1);
return true;
}
next(): T {
if (this.nodes.length === 0) throw new Error("no nodes available");
let best = this.nodes[0];
for (const node of this.nodes) {
node.current += node.weight;
if (node.current > best.current) best = node;
}
best.current -= this.totalWeight;
return best.value;
}
get size(): number {
return this.nodes.length;
}
}Report a problem with this exampleOpens a pre-filled issue on GitHub.