RandomGenerator.ts 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import { inject, injectable, postConstruct } from 'inversify';
  2. import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
  3. import * as md5 from 'md5';
  4. import { Chance } from 'chance';
  5. import { IInitializable } from '../interfaces/IInitializable';
  6. import { IOptions } from '../interfaces/options/IOptions';
  7. import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
  8. import { ISourceCode } from '../interfaces/ISourceCode';
  9. import { initializable } from '../decorators/Initializable';
  10. import { Utils } from './Utils';
  11. @injectable()
  12. export class RandomGenerator implements IRandomGenerator, IInitializable {
  13. /**
  14. * @type {string}
  15. */
  16. public static readonly randomGeneratorPool: string = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
  17. /**
  18. * @type {string}
  19. */
  20. public static readonly randomGeneratorPoolNumbers: string = '0123456789';
  21. /**
  22. * @type {string}
  23. */
  24. public static readonly randomGeneratorPoolHexadecimal: string = `abcdef${RandomGenerator.randomGeneratorPoolNumbers}`;
  25. /**
  26. * @type {number}
  27. */
  28. @initializable()
  29. public seed: number;
  30. /**
  31. * @type {IOptions}
  32. */
  33. private readonly options: IOptions;
  34. /**
  35. * @type {number}
  36. */
  37. private randomVariableNameAdditionalLength: number = 0;
  38. /**
  39. * @type {Set<string>}
  40. */
  41. private readonly randomVariableNameSet: Set <string> = new Set();
  42. /**
  43. * @type {Chance.Chance | Chance.SeededChance}
  44. */
  45. @initializable()
  46. private randomGenerator: Chance.Chance | Chance.SeededChance;
  47. /**
  48. * @type {ISourceCode}
  49. */
  50. private readonly sourceCode: ISourceCode;
  51. /**
  52. * @param {ISourceCode} sourceCode
  53. * @param {IOptions} options
  54. */
  55. constructor (
  56. @inject(ServiceIdentifiers.ISourceCode) sourceCode: ISourceCode,
  57. @inject(ServiceIdentifiers.IOptions) options: IOptions
  58. ) {
  59. this.sourceCode = sourceCode;
  60. this.options = options;
  61. }
  62. @postConstruct()
  63. public initialize (): void {
  64. const getRandomInteger: (min: number, max: number) => number = (min: number, max: number) => {
  65. return Math.floor(Math.random() * (max - min + 1) + min);
  66. };
  67. /**
  68. * We need to add numbers from md5 hash of source code to input seed to prevent same String Array name
  69. * for different bundles with same seed
  70. *
  71. * @returns {number}
  72. */
  73. const getSeed: () => number = (): number => {
  74. const md5Hash: string = md5(this.sourceCode.getSourceCode());
  75. return this.seed + Number(md5Hash.replace(/\D/g, ''));
  76. };
  77. this.seed = this.options.seed !== 0 ? this.options.seed : getRandomInteger(0, 999999999);
  78. this.randomGenerator = new Chance(getSeed());
  79. console.log(`Seed is ${this.seed}`);
  80. }
  81. /**
  82. * @returns {number}
  83. */
  84. public getMathRandom (): number {
  85. return this.getRandomInteger(0, 99999) / 100000;
  86. }
  87. /**
  88. * @param {number} min
  89. * @param {number} max
  90. * @returns {number}
  91. */
  92. public getRandomFloat (min: number, max: number): number {
  93. return this.getRandomGenerator().floating({
  94. min: min,
  95. max: max,
  96. fixed: 7
  97. });
  98. }
  99. /**
  100. * @returns {Chance.Chance}
  101. */
  102. public getRandomGenerator (): Chance.Chance {
  103. return this.randomGenerator;
  104. }
  105. /**
  106. * @param {number} min
  107. * @param {number} max
  108. * @returns {number}
  109. */
  110. public getRandomInteger (min: number, max: number): number {
  111. return this.getRandomGenerator().integer({
  112. min: min,
  113. max: max
  114. });
  115. }
  116. /**
  117. * @param {number} length
  118. * @param {string} pool
  119. * @returns {string}
  120. */
  121. public getRandomString (length: number, pool: string = RandomGenerator.randomGeneratorPool): string {
  122. return this.getRandomGenerator().string({ length, pool });
  123. }
  124. /**
  125. * @param {number} length
  126. * @returns {string}
  127. */
  128. public getRandomVariableName (length: number): string {
  129. const prefix: string = `_${Utils.hexadecimalPrefix}`;
  130. const rangeMinInteger: number = 10000;
  131. const rangeMaxInteger: number = 99999999;
  132. const randomInteger: number = this.getRandomInteger(rangeMinInteger, rangeMaxInteger);
  133. const hexadecimalNumber: string = Utils.decToHex(randomInteger);
  134. const randomVariableNameLength: number = length + this.randomVariableNameAdditionalLength;
  135. const randomVariableName: string = `${prefix}${hexadecimalNumber.repeat(2).substr(0, randomVariableNameLength)}`;
  136. if (this.randomVariableNameSet.has(randomVariableName)) {
  137. this.randomVariableNameAdditionalLength++;
  138. return this.getRandomVariableName(randomVariableNameLength);
  139. }
  140. this.randomVariableNameSet.add(randomVariableName);
  141. return randomVariableName;
  142. }
  143. }