92 lines
2.4 KiB
JavaScript
92 lines
2.4 KiB
JavaScript
/** @odoo-module */
|
|
|
|
import { isNil, stringToNumber } from "../hoot_utils";
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Global
|
|
//-----------------------------------------------------------------------------
|
|
|
|
const {
|
|
Math,
|
|
Number: { isNaN: $isNaN, parseFloat: $parseFloat },
|
|
Object: { defineProperties: $defineProperties },
|
|
} = globalThis;
|
|
const { floor: $floor, random: $random } = Math;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Internal
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* @param {unknown} [seed]
|
|
*/
|
|
const toValidSeed = (seed) => {
|
|
if (isNil(seed)) {
|
|
return generateSeed();
|
|
}
|
|
const nSeed = $parseFloat(seed);
|
|
return $isNaN(nSeed) ? stringToNumber(nSeed) : nSeed;
|
|
};
|
|
|
|
const DEFAULT_SEED = 1e16;
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Exports
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/**
|
|
* Generates a random 16-digit number.
|
|
* This function uses the native (unpatched) {@link Math.random} method.
|
|
*/
|
|
export function generateSeed() {
|
|
return $floor($random() * 1e16);
|
|
}
|
|
|
|
/**
|
|
* Returns a seeded random number generator equivalent to the native
|
|
* {@link Math.random} method.
|
|
*
|
|
* It exposes a `seed` property that can be changed at any time to reset the
|
|
* generator.
|
|
*
|
|
* @param {number} seed
|
|
* @example
|
|
* const randA = makeSeededRandom(1e16);
|
|
* const randB = makeSeededRandom(1e16);
|
|
* randA() === randB(); // true
|
|
* @example
|
|
* const random = makeSeededRandom(1e16);
|
|
* random() === random(); // false
|
|
*/
|
|
export function makeSeededRandom(seed) {
|
|
function random() {
|
|
state ^= (state << 13) >>> 0;
|
|
state ^= (state >>> 17) >>> 0;
|
|
state ^= (state << 5) >>> 0;
|
|
|
|
return ((state >>> 0) & 0x7fffffff) / 0x7fffffff; // Normalize to [0, 1)
|
|
}
|
|
|
|
let state = seed;
|
|
|
|
$defineProperties(random, {
|
|
seed: {
|
|
get() {
|
|
return seed;
|
|
},
|
|
set(value) {
|
|
seed = toValidSeed(value);
|
|
state = seed;
|
|
},
|
|
},
|
|
});
|
|
|
|
return random;
|
|
}
|
|
|
|
/**
|
|
* `random` function used internally to not generate unwanted calls on global
|
|
* `Math.random` function (and possibly having a different seed).
|
|
*/
|
|
export const internalRandom = makeSeededRandom(DEFAULT_SEED);
|