UNPKG

atriusmaps-node-sdk

Version:

This project provides an API to Atrius Personal Wayfinder maps within a Node environment. See the README.md for more information

125 lines (109 loc) 4.17 kB
'use strict'; // Simple seedable random number generator - NOT cryptographicaly secure! function mulberry32 (seed) { return function () { let t = seed += 0x6D2B79F5; t = Math.imul(t ^ (t >>> 15), t | 1); t ^= t + Math.imul(t ^ (t >>> 7), t | 61); return ((t ^ (t >>> 14)) >>> 0) / 4294967296 } } // ONLY use this for making tests deterministic - otherwise its a bad practice const isCypress = typeof window !== 'undefined' && window.Cypress; const random = isCypress ? mulberry32(12345678) : Math.random; /** * Returns a random integer between the min and max values. Can also * be called with a single value which becomes the max and min is set to 0. * @param {integer} min minimum integer value to return (inclusive) * @param {integer} max maximum integer value to return (exclusive) * @returns random integer between min and max. */ const rand = (min, max) => { if (max == null) { max = min; min = 0; } return Math.floor(random() * (max - min) + min) }; /** * Returns a random list of length `size` with unique integers from 0 to `max` - 1. * * No number will repeat. If `size > max`, it is clamped to `max`. * If `max` is not provided, it defaults to `size`, resulting in a random shuffle of [0..size-1]. * * This is useful for randomly selecting a subset of indices or shuffling a range. * * For example: * randomSet(3, 5) → [3, 2, 0] * randomSet(5) → [1, 4, 0, 3, 2] // full shuffle of 0..4 * * @param {number} size - Number of unique values to return * @param {number} [max] - Range upper bound (exclusive); defaults to `size` * @returns {number[]} An array of unique random integers from 0 to max-1 */ function randomSet (size, max) { if (!max) max = size; if (size > max) size = max; const result = []; // Threshold for choosing sparse vs dense algorithm // If we're selecting less than 30% of the range, collisions are rare const SPARSITY_THRESHOLD = 0.3; const isSparse = (size / max) < SPARSITY_THRESHOLD; if (isSparse) { // Sparse strategy: randomly generate values and skip duplicates // Fast when the number of needed values is small relative to the range const seen = new Set(); while (result.length < size) { const i = rand(max); if (!seen.has(i)) { seen.add(i); result.push(i); } } } else { // Dense strategy: partial in-place Fisher-Yates shuffle // More efficient when selecting a large portion of the range const source = Array.from({ length: max }, (_, i) => i); for (let i = 0; i < size; i++) { // Select a random index in the shrinking source array const index = rand(max - i); // Add the selected value to the result result.push(source[index]); // Move the last unchosen item into the chosen spot to "remove" it source[index] = source[max - i - 1]; } } return result } /** * Given a source array and an array of indices, return a new array * containing the source elements at the specified indices. * * @param {Array} array - The source array * @param {number[]} map - Array of indices to pull from the source * @returns {Array} - Mapped array */ const getMappedArray = (array, map) => map.map(i => array[i]); /** * Returns a new array containing the elements of the input array in random order. * Original array is not modified. * * @param {Array} array - The array to shuffle * @returns {Array} - A new randomized array */ const randomizeArray = array => getMappedArray(array, randomSet(array.length)); /** * Returns a random selection of `num` elements from the array, in random order. * Original array is not modified. If `num` is not specified, returns a single random item. * If `num > array.length`, it is clamped to the array length. * * @param {Array} array - The array to sample from * @param {number} [num=1] - Number of items to pick * @returns {Array} - Randomly selected items */ const arrayPick = (array, num = 1) => getMappedArray(array, randomSet(num, array.length)); exports.arrayPick = arrayPick; exports.rand = rand; exports.randomSet = randomSet; exports.randomizeArray = randomizeArray;