--- /dev/null
+// given an array, will grab a weighted version of it
+import { random } from 'lodash';
+import { logger } from './logger';
+
+export type Weighted = {
+ weight: number;
+}
+
+export function weighted<T>(options: T[], getWeight: (item: T) => number, weightPrecision: number = 100, defaultReturn?: T): T | undefined {
+ let maxWeight = 0;
+ let segments: {start: number, end: number, item: T}[] = [];
+
+ options.forEach(option => {
+ const start = maxWeight;
+ maxWeight += (getWeight(option) * weightPrecision)
+ const end = maxWeight;
+ segments.push({
+ start: start,
+ end: end,
+ item: option
+ });
+ });
+
+ const selection = random(0, 100);
+
+ logger.info({
+ random: selection,
+ maxWeight: maxWeight
+ }, 'random weighted selection for item');
+
+ if(selection >= maxWeight) {
+ // there's a chance that the player actually gest nothing!
+ return undefined;
+ }
+
+ const found = segments.find(segment => {
+ return segment.start <= selection && segment.end >= selection;
+ });
+
+ return found ? found.item : defaultReturn;
+}