UNPKG

@gent-js/gent

Version:

template-based data generator.

67 lines (66 loc) 1.98 kB
import { faker } from "@faker-js/faker"; const DEFAULT_WEIGHT = 1; const MIN_WEIGHT = 0; const MAX_WEIGHT = 2 ** 16; export class WeightedItemFeeder { totalWeight = -1; normalizedWeightedItems; constructor(...weightedItems) { this.normalizedWeightedItems = weightedItems.map(normalizeWeightedItem); this.updateTotalWeight(); } get size() { return this.normalizedWeightedItems.length; } addItem(item, weight = DEFAULT_WEIGHT) { const weightedItem = { content: item, weight: weight, }; this.addWeightedItem(weightedItem); } addWeightedItem(weightedItem) { this.normalizedWeightedItems.push(normalizeWeightedItem(weightedItem)); this.updateTotalWeight(); } getItem() { const totalWeight = this.totalWeight; if (totalWeight < MIN_WEIGHT) { return undefined; } const targetAccumWeight = faker.number.float({ min: MIN_WEIGHT, max: totalWeight, }); let accumWeight = MIN_WEIGHT; const weightedItem = this.normalizedWeightedItems.find(({ weight }) => { accumWeight = accumWeight + weight; if (targetAccumWeight <= accumWeight) { return true; } return false; }); return weightedItem?.content; } updateTotalWeight() { this.totalWeight = this.normalizedWeightedItems.reduce((sum, { weight }) => { return sum + weight; }, 0); } } function normalizeWeightedItem(weightedItem) { let weight; if (typeof weightedItem.weight === "number") { weight = weightedItem.weight; } else { weight = DEFAULT_WEIGHT; } return { content: weightedItem.content, weight: normalizeWeight(weight), }; } export function normalizeWeight(value) { return Math.min(Math.max(value, MIN_WEIGHT), MAX_WEIGHT); }