All files / generator NumberGenerator.ts

96.87% Statements 31/32
92.1% Branches 35/38
100% Functions 2/2
96.66% Lines 29/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67                  7x 7x                     183x 183x 183x 183x 183x   183x 123x 123x 123x 123x 123x       123x 103x   123x 103x   123x   123x       60x 60x   60x 60x   60x 40x   20x 20x   60x   60x        
import { BaseGenerator } from './BaseGenerator'
import { type GeneratorOptions } from './BaseGenerator'
import type { NumberOptions } from '../schema/data'
import RNG from '../util/rng'
 
export default class NumberGenerator extends BaseGenerator {
  protected rng: RNG
 
  constructor(opts: GeneratorOptions) {
    super(opts)
    this.rng = new RNG(opts.seed)
  }
 
  /**
   * Generates a random number based on the provided options.
   * The default distribution is uniform.
   * By default, it generates a single integer between 0 and 200.
   * If type is 'float', generates a floating-point number between 0.0 and 200.0. 
   * If count > 1, returns an array of numbers.
   */
  generate(options: Partial<NumberOptions>): number[] | number {
    const type = options.type ?? 'integer'
    const mean = options.mean ?? (type === 'integer' ? 100 : 100.0)
    const stddev = options.stddev ?? (type === 'integer' ? 20 : 20.0)
    const precision = options.precision ?? (type === 'integer' ? 1 : 0.01)
    const count = options.count ?? 1
 
    if (options.distribution === 'normal') {
      const values = []
      for (let i = 0; i < count; i++) {
        let value = this.rng.normalFloat(mean, stddev)
        if (type === 'integer') {
          value = Math.round(value)
        } else E{
          value = Math.round(value / precision) * precision
        }
        if (options.minimum !== undefined) {
          value = Math.max(value, options.minimum)
        }
        if (options.maximum !== undefined) {
          value = Math.min(value, options.maximum)
        }
        values.push(value)
      }
      return count === 1 ? values[0] : values
    }
 
    // Default to uniform distribution
    const min = options.minimum ?? (type === 'integer' ? 0 : 0.0)
    const max = options.maximum ?? (type === 'integer' ? Math.max(min + 1, 200) : Math.max(min + 0.01, 200.0))
 
    const values = []
    for (let i = 0; i < count; i++) {
      let value: number
      if (type === 'integer') {
        value = this.rng.uniformInt(Math.ceil(min), Math.floor(max))
      } else {
        value = this.rng.uniformFloat(min, max)
        value = Math.round(value / precision) * precision
      }
      values.push(value)
    }
    return count === 1 ? values[0] : values
  }
 
}