Class: Dry::Effects::Providers::Random

Inherits:
Object
  • Object
show all
Defined in:
lib/dry/effects/providers/random.rb

Constant Summary collapse

DEFAULT_RANDOM =
::Random
DEFAULT =
-> _ { DEFAULT_RANDOM.rand }
DEFAULT_RANGE =
(0.0...1.0)

Instance Method Summary collapse

Instance Method Details

#build_generator(options) ⇒ Object



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/dry/effects/providers/random.rb', line 60

def build_generator(options)
  case options
  when Undefined
    DEFAULT
  when ::Hash
    if options.key?(:seed)
      random = ::Random.new(options[:seed])
    else
      random = DEFAULT_RANDOM
    end

    -> _ { random.rand }
  else
    generator = options

    lambda do |prev|
      prev.nil? ? generator.() : generator.(prev)
    end
  end
end

#call(options = Undefined) ⇒ Object



36
37
38
39
40
# File 'lib/dry/effects/providers/random.rb', line 36

def call(options = Undefined)
  @prev = nil
  @generator = build_generator(options)
  yield
end

#next_float(low, high) ⇒ Object



54
55
56
57
58
# File 'lib/dry/effects/providers/random.rb', line 54

def next_float(low, high)
  @prev = @generator.(@prev) % 1

  low + (@prev * (high - low))
end

#next_integer(low, high, exclude_end) ⇒ Object



42
43
44
45
46
47
48
49
50
51
52
# File 'lib/dry/effects/providers/random.rb', line 42

def next_integer(low, high, exclude_end)
  @prev = @generator.(@prev) % 1

  value = low + (@prev * (high - low)).round

  if value.eql?(high) && exclude_end
    low
  else
    value
  end
end

#rand(range_or_limit = nil) ⇒ Object



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# File 'lib/dry/effects/providers/random.rb', line 12

def rand(range_or_limit = nil)
  range_or_limit ||= DEFAULT_RANGE

  if range_or_limit.is_a?(::Range)
    low = range_or_limit.begin
    high = range_or_limit.end
    exclude_end = range_or_limit.exclude_end?
  elsif range_or_limit >= 1
    low = 0
    high = range_or_limit.floor
    exclude_end = true
  else
    low = 0.0
    high = range_or_limit.to_f
    exclude_end = true
  end

  if low.is_a?(::Integer)
    next_integer(low, high, exclude_end)
  else
    next_float(low, high)
  end
end