Aimless.js

The missing JavaScript randomness library.

README

Aimless.js

Why?


Outside of large game engines and frameworks, there is very little support for generating random numbers in JavaScript.  Sure, there are quite a number of substitutes for the native Math.random function, but what if I wanted to generate a random number within a range?  Better yet, what if I wanted to do anything but get a number between 0 and 1?

Aimless is the missing JS randomness library.  It's tiny (< 6kB), unopinionated, dependency-free, and provides a variety of helpful random number utilities.  Best of all, it's compatible with all your favorite PRNGs.

Getting Started


Follow these steps:


Install


Install and add it to your package.json dependencies.

  1. ```
  2. $ npm install aimless.js --save
  3. ```

Then import utility functions into the file where you'll use them.

  1. ```es6
  2. import { bool, intRange } from 'aimless.js'
  3. ```

Using Custom PRNG


Aimless.js is compatible with any custom PRNG that returns a number num >= 0 and num < 1.  Every function accepts an engine to be used.

  1. ```es6
  2. import { bool } from 'aimless.js'

  3. const engine = () => 0
  4. bool(engine) // false
  5. ```

Additionally, every function in Aimless has a counterpart named withEngine.  This function will return its counterpart with a closure around your engine, so you don't need to pass it every time.

  1. ```es6
  2. import { boolWithEngine } from 'aimless.js'

  3. const engine = () => 0
  4. const bool = boolWithEngine(engine)
  5. bool() // false
  6. ```

Every function will default to using the provided defaultEngine if no custom engine is provided.  The default engine uses crypto.getrandomvalues when available, with a fallback of Math.random.

API



bool(engine)


Returns either true or false.

char(string, engine)


Returns a random character from the provided string.

  1. ```es6
  2. const randomChar = char('the missing JS randomness library')
  3. // could return 's', ' ', 'l', etc
  4. ```

customDist(function, engine)


Returns a random number following a custom distribution of your choosing.  function should take in a number between 0 and 1.

  1. ```es6
  2. const randomOfCustomDist = customDist(
  3.     (randomNumber) => randomNumber / 2
  4. )
  5. ```

exponentialDist(lambda, engine)


Returns a random number following an exponential distribution with the provided lambda.

  1. ```es6
  2. const samples = []
  3. const lambda = 0.5

  4. for (let i = 0; i < 100000; i++) {
  5.     const randomValue = exponentialDist(lambda)
  6.     samples.push(randomValue)
  7. }

  8. // you can expect the mean of `samples` to be (1 / lambda) +/- 0.01,
  9. // generating more samples will ensure a mean of (1 / lambda)
  10. ```

floatRange(min, max, engine)


Returns a random float between min and max.

  1. ```es6
  2. const randomFloat = floatRange(0.1, 0.2)
  3. ```

intRange(min, max, engine)


Returns a random integer between min and max.

  1. ```es6
  2. const randomInteger = intRange(5, 10)
  3. ```

intSequence(min, max, engine)


Returns an array with all integers between min and max in random order.

  1. ```es6
  2. const intSeq = intSequence(-1, 3)
  3. // could return [3,-1,2,1,0], [0,2,-1,3,1], etc
  4. ```

normalDist(mean, stdDev, engine)


Returns a random number following a normal distribution with mean mean and standard deviation stdDev.

  1. ```es6
  2. const samples = []

  3. for (let i = 0; i < 100000; i++) {
  4.     const randomValue = normalDist(0, 1)
  5.     samples.push(randomValue)
  6. }

  7. // you can expect the mean of `samples` to be 0 +/- 0.01,
  8. // generating more samples will ensure a mean of 0
  9. ```

normalFloat(engine)


Returns a random float between -1 and 1.

oneOf(array, engine)


Returns a random item from the array provided.

  1. ```es6
  2. const randomItem = oneOf([1,2,3])
  3. const randomObj = oneOf([{a:1}, {b:2}, {c:3}])
  4. ```

seedFunc(seed)


Returns a seeded random number generator.  Seeded RNGs produce random numbers, but are predictable if you use the same seed.  note: the Park-Miller PRNG is used to provide the seeded function, therefore, an engine is not accepted.

  1. ```es6
  2. const seededFunction = seedFunc(1)
  3. seededFunction() // 0.000007825903601782307
  4. seededFunction() // 0.13153778773875702
  5. seededFunction() // 0.7556053220812281

  6. const newSeeded = seedFunc(1)
  7. newSeeded() // 0.000007825903601782307
  8. newSeeded() // 0.13153778773875702
  9. newSeeded() // 0.7556053220812281
  10. ```

sequence(array, engine)


Returns a new array with the same items contained in array but in random order.

  1. ```es6
  2. const randomSeq = sequence([1,2,3])
  3. // could return [3,1,2], [2,3,1], etc.
  4. ```

sign(engine)


Returns either -1 or 1.

uniqFuncIntRange(min, max, engine)


Returns a unique random number between min and max, using the provided engine.  If no engine is passed, the defaultEngine will be used.  If there are no unique values left to return, null will be returned.

  1. ```es6
  2. const uniqueRNG = uniqFuncIntRange(1, 3)
  3. uniqueRNG() // 2
  4. uniqueRNG() // 3
  5. uniqueRNG() // 1
  6. uniqueRNG() // null
  7. ```

uniqFuncSequence(array, engine)


Returns a unique random number from the provided array, using the provided engine.  If no engine is passed, the defaultEngine will be used.  If there are no unique values left to return, null will be returned.

  1. ```es6
  2. const uniqueRNG = uniqFuncSequence([10, 20, 30])
  3. uniqueRNG() // 20
  4. uniqueRNG() // 30
  5. uniqueRNG() // 10
  6. uniqueRNG() // null
  7. ```

uuid(engine)


Returns a valid RFC4122 version4 ID hex string, using the provided engine.

  1. ```es6
  2. const id = uuid()
  3. console.log(id) // ef486db4-7f49-43b3-a1ea-b0e0a22bc944
  4. ```

weighted(numbers, weights, engine)


Returns one of the numbers provided, biased towards the corresponding weights provided.  numbers can include floats.

  1. ```es6
  2. const weightedDiceRoll = weighted(
  3.     [1,2,3,4,5,6],
  4.     [1,1,1,1,1,10]
  5. )
  6. // will return 6 much more often than the other options
  7. ```

Browser Support


Aimless relies on ES5 array methods, and is supported in all modern browsers.  Support for legacy or depricated browsers is not planned.

License


MIT. © 2023 Christopher Cavalea