math.ts 3.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. /** Ensures the passed {@linkcode value} always stays between {@linkcode min} and {@linkcode max} */
  2. export function clamp(value: number, min: number, max: number): number {
  3. return Math.max(Math.min(value, max), min);
  4. }
  5. /**
  6. * Transforms the value parameter from the numerical range `range1min` to `range1max` to the numerical range `range2min` to `range2max`
  7. * For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
  8. */
  9. export function mapRange(value: number, range1min: number, range1max: number, range2min: number, range2max: number): number;
  10. /**
  11. * Transforms the value parameter from the numerical range `0` to `range1max` to the numerical range `0` to `range2max`
  12. * For example, you can map the value 2 in the range of 0-5 to the range of 0-10 and you'd get a 4 as a result.
  13. */
  14. export function mapRange(value: number, range1max: number, range2max: number): number;
  15. export function mapRange(value: number, range1min: number, range1max: number, range2min?: number, range2max?: number): number {
  16. // overload
  17. if(typeof range2min === "undefined" || range2max === undefined) {
  18. range2max = range1max;
  19. range2min = 0;
  20. range1max = range1min;
  21. range1min = 0;
  22. }
  23. if(Number(range1min) === 0.0 && Number(range2min) === 0.0)
  24. return value * (range2max / range1max);
  25. return (value - range1min) * ((range2max - range2min) / (range1max - range1min)) + range2min;
  26. }
  27. /**
  28. * Returns a random number between {@linkcode min} and {@linkcode max} (inclusive)
  29. * Set {@linkcode enhancedEntropy} to true to use `crypto.getRandomValues()` for better cryptographic randomness (this also makes it take longer to generate)
  30. */
  31. export function randRange(min: number, max: number, enhancedEntropy?: boolean): number
  32. /**
  33. * Returns a random number between 0 and {@linkcode max} (inclusive)
  34. * Set {@linkcode enhancedEntropy} to true to use `crypto.getRandomValues()` for better cryptographic randomness (this also makes it take longer to generate)
  35. */
  36. export function randRange(max: number, enhancedEntropy?: boolean): number
  37. /**
  38. * Returns a random number between {@linkcode min} and {@linkcode max} (inclusive)
  39. * Set {@linkcode enhancedEntropy} to true to use `crypto.getRandomValues()` for better cryptographic randomness (this also makes it take longer to generate)
  40. */
  41. export function randRange(...args: (number | boolean | undefined)[]): number {
  42. let min: number, max: number, enhancedEntropy = false;
  43. // using randRange(min, max)
  44. if(typeof args[0] === "number" && typeof args[1] === "number")
  45. [ min, max ] = args;
  46. // using randRange(max)
  47. else if(typeof args[0] === "number" && typeof args[1] !== "number") {
  48. min = 0;
  49. [ max ] = args;
  50. }
  51. else
  52. throw new TypeError(`Wrong parameter(s) provided - expected: "number" and "number|undefined", got: "${typeof args[0]}" and "${typeof args[1]}"`);
  53. if(typeof args[2] === "boolean")
  54. enhancedEntropy = args[2];
  55. else if(typeof args[1] === "boolean")
  56. enhancedEntropy = args[1];
  57. min = Number(min);
  58. max = Number(max);
  59. if(isNaN(min) || isNaN(max))
  60. return NaN;
  61. if(min > max)
  62. throw new TypeError("Parameter \"min\" can't be bigger than \"max\"");
  63. if(enhancedEntropy) {
  64. const uintArr = new Uint8Array(1);
  65. crypto.getRandomValues(uintArr);
  66. return Number(Array.from(
  67. uintArr,
  68. (v) => Math.round(mapRange(v, 0, 255, min, max)).toString(10).substring(0, 1),
  69. ).join(""));
  70. }
  71. else
  72. return Math.floor(Math.random() * (max - min + 1)) + min;
  73. }
  74. /** Calculates the amount of digits in the given number - the given number or string will be passed to the `Number()` constructor. Returns NaN if the number is invalid. */
  75. export function digitCount(num: number | string): number {
  76. return num === 0
  77. ? 1
  78. : Math.floor(
  79. Math.log10(Math.abs(Number(num))) + 1
  80. );
  81. }